aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/components/gfx/render_task.rs23
-rw-r--r--src/components/main/compositing/mod.rs21
-rw-r--r--src/components/main/constellation.rs122
-rw-r--r--src/components/main/layout/layout_task.rs1
-rw-r--r--src/components/main/layout/text.rs2
-rw-r--r--src/components/main/pipeline.rs19
-rw-r--r--src/components/main/platform/common/glut_windowing.rs41
-rw-r--r--src/components/main/windowing.rs12
-rw-r--r--src/components/msg/compositor.rs2
-rw-r--r--src/components/msg/constellation.rs5
-rw-r--r--src/components/script/dom/characterdata.rs2
-rw-r--r--src/components/script/dom/node.rs2
-rw-r--r--src/components/script/html/cssparse.rs1
-rw-r--r--src/components/script/script_task.rs55
-rw-r--r--src/components/util/time.rs2
m---------src/support/alert/rust-alert0
16 files changed, 213 insertions, 97 deletions
diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs
index db0083d5876..b0fed806ef2 100644
--- a/src/components/gfx/render_task.rs
+++ b/src/components/gfx/render_task.rs
@@ -21,7 +21,6 @@ use render_context::RenderContext;
use std::cell::Cell;
use std::comm::{Chan, Port, SharedChan};
use std::uint;
-use std::util::replace;
use servo_util::time::{ProfilerChan, profile};
use servo_util::time;
@@ -73,7 +72,7 @@ priv struct RenderTask<C> {
/// A token that grants permission to send paint messages to compositor
compositor_token: Option<~CompositorToken>,
/// Cached copy of last layers rendered
- next_paint_msg: Option<(LayerBufferSet, Size2D<uint>)>,
+ last_paint_msg: Option<(LayerBufferSet, Size2D<uint>)>,
}
impl<C: RenderListener + Owned> RenderTask<C> {
@@ -108,7 +107,7 @@ impl<C: RenderListener + Owned> RenderTask<C> {
constellation_chan: constellation_chan.take(),
compositor_token: None,
- next_paint_msg: None,
+ last_paint_msg: None,
};
render_task.start();
@@ -129,11 +128,9 @@ impl<C: RenderListener + Owned> RenderTask<C> {
}
TokenBestowMsg(token) => {
self.compositor_token = Some(token);
- let next_paint_msg = replace(&mut self.next_paint_msg, None);
- match next_paint_msg {
- Some((layer_buffer_set, layer_size)) => {
- println("retrieving cached paint msg");
- self.compositor.paint(layer_buffer_set, layer_size);
+ match self.last_paint_msg {
+ Some((ref layer_buffer_set, ref layer_size)) => {
+ self.compositor.paint(layer_buffer_set.clone(), *layer_size);
self.compositor.set_render_state(IdleRenderState);
}
None => {}
@@ -162,7 +159,7 @@ impl<C: RenderListener + Owned> RenderTask<C> {
}
self.compositor.set_render_state(RenderingRenderState);
- do profile(time::RenderingCategory, self.profiler_chan.clone()) {
+ do time::profile(time::RenderingCategory, self.profiler_chan.clone()) {
let tile_size = self.opts.tile_size;
// FIXME: Try not to create a new array here.
@@ -235,12 +232,10 @@ impl<C: RenderListener + Owned> RenderTask<C> {
debug!("render_task: returning surface");
if self.compositor_token.is_some() {
- self.compositor.paint(layer_buffer_set, render_layer.size);
- }
- else {
- println("caching paint msg");
- self.next_paint_msg = Some((layer_buffer_set, render_layer.size));
+ self.compositor.paint(layer_buffer_set.clone(), render_layer.size);
}
+ debug!("caching paint msg");
+ self.last_paint_msg = Some((layer_buffer_set, render_layer.size));
self.compositor.set_render_state(IdleRenderState);
}
}
diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs
index 873c46a645a..e8a847e5c30 100644
--- a/src/components/main/compositing/mod.rs
+++ b/src/components/main/compositing/mod.rs
@@ -4,12 +4,14 @@
use platform::{Application, Window};
use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent, ResizeEvent};
-use script::script_task::{LoadMsg, SendEventMsg};
+use script::script_task::{LoadMsg, NavigateMsg, SendEventMsg};
use script::layout_interface::{LayoutChan, RouteScriptMsg};
use windowing::{ApplicationMethods, WindowMethods, WindowMouseEvent, WindowClickEvent};
use windowing::{WindowMouseDownEvent, WindowMouseUpEvent};
+
use servo_msg::compositor::{RenderListener, LayerBufferSet, RenderState};
use servo_msg::compositor::{ReadyState, ScriptListener};
+use servo_msg::constellation;
use gfx::render_task::{RenderChan, ReRenderMsg};
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods, current_gl_context};
@@ -32,6 +34,7 @@ use servo_util::{time, url};
use servo_util::time::profile;
use servo_util::time::ProfilerChan;
+pub use windowing;
/// The implementation of the layers-based compositor.
#[deriving(Clone)]
@@ -180,13 +183,22 @@ impl CompositorTask {
let update_layout_callbacks: @fn(LayoutChan) = |layout_chan: LayoutChan| {
let layout_chan_clone = layout_chan.clone();
+ do window.set_navigation_callback |direction| {
+ let direction = match direction {
+ windowing::Forward => constellation::Forward,
+ windowing::Back => constellation::Back,
+ };
+ layout_chan_clone.send(RouteScriptMsg(NavigateMsg(direction)));
+ }
+
+ let layout_chan_clone = layout_chan.clone();
// Hook the windowing system's resize callback up to the resize rate limiter.
do window.set_resize_callback |width, height| {
let new_size = Size2D(width as int, height as int);
if *window_size != new_size {
debug!("osmain: window resized to %ux%u", width, height);
*window_size = new_size;
- layout_chan_clone.chan.send(RouteScriptMsg(SendEventMsg(ResizeEvent(width, height))));
+ layout_chan_clone.send(RouteScriptMsg(SendEventMsg(ResizeEvent(width, height))));
} else {
debug!("osmain: dropping window resize since size is still %ux%u", width, height);
}
@@ -197,7 +209,7 @@ impl CompositorTask {
// When the user enters a new URL, load it.
do window.set_load_url_callback |url_string| {
debug!("osmain: loading URL `%s`", url_string);
- layout_chan_clone.chan.send(RouteScriptMsg(LoadMsg(url::make_url(url_string.to_str(), None))));
+ layout_chan_clone.send(RouteScriptMsg(LoadMsg(url::make_url(url_string.to_str(), None))));
}
let layout_chan_clone = layout_chan.clone();
@@ -229,7 +241,7 @@ impl CompositorTask {
event = MouseUpEvent(button, world_mouse_point(layer_mouse_point));
}
}
- layout_chan_clone.chan.send(RouteScriptMsg(SendEventMsg(event)));
+ layout_chan_clone.send(RouteScriptMsg(SendEventMsg(event)));
}
};
@@ -410,6 +422,7 @@ impl CompositorTask {
window.set_needs_display()
}
+
// Enter the main event loop.
while !*done {
// Check for new messages coming from the rendering task.
diff --git a/src/components/main/constellation.rs b/src/components/main/constellation.rs
index bed38b8739f..c522bb033ef 100644
--- a/src/components/main/constellation.rs
+++ b/src/components/main/constellation.rs
@@ -12,14 +12,15 @@ use gfx::opts::Opts;
use gfx::render_task::{TokenBestowMsg, TokenProcureMsg};
use pipeline::Pipeline;
use servo_msg::compositor::{CompositorToken};
-use servo_msg::constellation::{ConstellationChan, ExitMsg, LoadUrlMsg, Msg, RendererReadyMsg};
-use servo_msg::constellation::TokenSurrenderMsg;
-use script::script_task::{ExecuteMsg, LoadMsg};
+use servo_msg::constellation::{ConstellationChan, ExitMsg, LoadUrlMsg, Msg, NavigateMsg};
+use servo_msg::constellation::{Forward, Back, RendererReadyMsg, TokenSurrenderMsg};
+use script::script_task::ExecuteMsg;
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 std::hashmap::HashMap;
+use std::util::replace;
pub struct Constellation {
chan: ConstellationChan,
@@ -30,12 +31,20 @@ pub struct Constellation {
pipelines: HashMap<uint, Pipeline>,
navigation_context: NavigationContext,
next_id: uint,
- current_token_holder: Option<uint>,
- loading: Option<uint>,
+ current_token_bearer: Option<uint>,
+ next_token_bearer: Option<(uint, NavigationType)>,
+ compositor_token: Option<~CompositorToken>,
profiler_chan: ProfilerChan,
opts: Opts,
}
+/// Represents the two different ways to which a page can be navigated
+enum NavigationType {
+ Load, // entered or clicked on a url
+ Navigate, // browser forward/back buttons
+}
+
+/// Stores the ID's of the pipelines previous and next in the browser's history
pub struct NavigationContext {
previous: ~[uint],
next: ~[uint],
@@ -52,18 +61,16 @@ impl NavigationContext {
}
pub fn back(&mut self) -> uint {
- do self.current.mutate |id| {
- self.next.push(id);
- self.previous.pop()
- }
+ self.next.push(self.current.get());
+ self.current = Some(self.previous.pop());
+ debug!("previous: %? next: %? current: %?", self.previous, self.next, self.current);
self.current.get()
}
pub fn forward(&mut self) -> uint {
- do self.current.mutate |id| {
- self.previous.push(id);
- self.next.pop()
- }
+ self.previous.push(self.current.get());
+ self.current = Some(self.next.pop());
+ debug!("previous: %? next: %? current: %?", self.previous, self.next, self.current);
self.current.get()
}
@@ -102,8 +109,9 @@ impl Constellation {
pipelines: HashMap::new(),
navigation_context: NavigationContext::new(),
next_id: 0,
- current_token_holder: None,
- loading: None,
+ current_token_bearer: None,
+ next_token_bearer: None,
+ compositor_token: Some(~CompositorToken::new()),
profiler_chan: profiler_chan.clone(),
opts: opts.take(),
};
@@ -122,17 +130,19 @@ impl Constellation {
}
}
+ /// Helper function for getting a unique pipeline ID
fn get_next_id(&mut self) -> uint {
let id = self.next_id;
self.next_id = id + 1;
id
}
+ /// Handles loading pages, navigation, and granting access to the compositor
fn handle_request(&mut self, request: Msg) -> bool {
match request {
LoadUrlMsg(url) => {
let pipeline_id = self.get_next_id();
- let pipeline = Pipeline::create(pipeline_id,
+ let mut pipeline = Pipeline::create(pipeline_id,
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
@@ -142,23 +152,41 @@ impl Constellation {
if url.path.ends_with(".js") {
pipeline.script_chan.send(ExecuteMsg(url));
} else {
- pipeline.script_chan.send(LoadMsg(url));
- self.loading = Some(pipeline_id);
+ pipeline.load(url);
+ self.next_token_bearer = Some((pipeline_id, Load));
}
self.pipelines.insert(pipeline_id, pipeline);
}
+ NavigateMsg(direction) => {
+ debug!("received message to navigate %?", direction);
+ let destination_id = match direction {
+ Forward => {
+ if self.navigation_context.next.is_empty() {
+ debug!("no next page to navigate to");
+ return true
+ }
+ self.navigation_context.forward()
+ }
+ Back => {
+ if self.navigation_context.previous.is_empty() {
+ debug!("no previous page to navigate to");
+ return true
+ }
+ self.navigation_context.back()
+ }
+ };
+ debug!("navigating to pipeline %u", destination_id);
+ self.pipelines.get(&destination_id).reload();
+ self.next_token_bearer = Some((destination_id, Navigate));
+ self.procure_or_bestow();
+ }
+
RendererReadyMsg(pipeline_id) => {
- let loading = self.loading.clone();
- do loading.map() |&id| {
+ let next_token_bearer = self.next_token_bearer;
+ for next_token_bearer.iter().advance |&(id, _)| {
if pipeline_id == id {
- match self.current_token_holder {
- Some(ref id) => {
- let current_holder = self.pipelines.get(id);
- current_holder.render_chan.send(TokenProcureMsg);
- }
- None => self.bestow_compositor_token(id, ~CompositorToken::new())
- }
+ self.procure_or_bestow();
}
};
}
@@ -166,9 +194,9 @@ impl Constellation {
TokenSurrenderMsg(token) => {
self.remove_active_pipeline();
let token = Cell::new(token);
- let loading = self.loading;
- do loading.map |&id| {
- self.bestow_compositor_token(id, token.take());
+ let next_token_bearer = self.next_token_bearer;
+ for next_token_bearer.iter().advance |&(id, nav_type)| {
+ self.bestow_compositor_token(id, token.take(), nav_type);
};
}
@@ -186,23 +214,45 @@ impl Constellation {
true
}
+ /// Either procures the token, sends the token to next bearer, or does nothing if waiting for token surrender.
+ fn procure_or_bestow(&mut self) {
+ let current_token_bearer = replace(&mut self.current_token_bearer, None);
+ match current_token_bearer {
+ Some(ref id) => {
+ let pipeline = self.pipelines.get(id);
+ pipeline.render_chan.send(TokenProcureMsg);
+ }
+ None => {
+ let compositor_token = replace(&mut self.compositor_token, None);
+ for compositor_token.iter().advance |&token| {
+ let (id, nav_type) = self.next_token_bearer.get();
+ self.bestow_compositor_token(id, token, nav_type);
+ }
+ }
+ };
+ }
+
fn remove_active_pipeline(&mut self) {
// FIXME(tkuehn): currently, pipelines are not removed at all
-// do self.current_token_holder.map |id| {
+// do self.current_token_bearer.map |id| {
// self.pipelines.pop(id).unwrap().exit();
// };
- self.current_token_holder = None;
+ self.current_token_bearer = None;
}
- fn bestow_compositor_token(&mut self, id: uint, compositor_token: ~CompositorToken) {
+ fn bestow_compositor_token(&mut self, id: uint, compositor_token: ~CompositorToken, navigation_type: NavigationType) {
let pipeline = self.pipelines.get(&id);
pipeline.render_chan.send(TokenBestowMsg(compositor_token));
self.compositor_chan.send(SetLayoutChan(pipeline.layout_chan.clone()));
self.compositor_chan.send(SetRenderChan(pipeline.render_chan.clone()));
- self.current_token_holder = Some(id);
- self.loading = None;
- self.navigation_context.navigate(id);
+ self.current_token_bearer = Some(id);
+ self.next_token_bearer = None;
+ // Don't navigate on Navigate type, because that is handled by forward/back
+ match navigation_type {
+ Load => self.navigation_context.navigate(id),
+ _ => {}
+ }
}
}
diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs
index cab29204559..0f93798af10 100644
--- a/src/components/main/layout/layout_task.rs
+++ b/src/components/main/layout/layout_task.rs
@@ -141,6 +141,7 @@ impl LayoutTask {
}
}
RouteScriptMsg(script_msg) => {
+ debug!("layout: routing %? to script task", script_msg);
self.route_script_msg(script_msg);
}
ExitMsg => {
diff --git a/src/components/main/layout/text.rs b/src/components/main/layout/text.rs
index b6b3e43eb99..59093ed70ff 100644
--- a/src/components/main/layout/text.rs
+++ b/src/components/main/layout/text.rs
@@ -234,7 +234,7 @@ impl TextRunScanner {
for clump.eachi |i| {
let range = new_ranges[i - self.clump.begin()];
if range.length() == 0 {
- error!("Elided an `UnscannedTextbox` because it was zero-length after \
+ debug!("Elided an `UnscannedTextbox` because it was zero-length after \
compression; %s",
in_boxes[i].debug_str());
loop
diff --git a/src/components/main/pipeline.rs b/src/components/main/pipeline.rs
index 0a801d7d577..dcb14569c4c 100644
--- a/src/components/main/pipeline.rs
+++ b/src/components/main/pipeline.rs
@@ -2,13 +2,14 @@
* 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::net::url::Url;
use compositing::CompositorChan;
use gfx::render_task::{RenderChan, RenderTask};
use gfx::render_task;
use gfx::opts::Opts;
use layout::layout_task::LayoutTask;
use script::layout_interface::LayoutChan;
-use script::layout_interface;
+use script::script_task::LoadMsg;
use servo_msg::constellation::{ConstellationChan};
use script::script_task::{ScriptTask, ScriptChan, ScriptMsg};
use script::script_task;
@@ -23,6 +24,8 @@ pub struct Pipeline {
script_chan: ScriptChan,
layout_chan: LayoutChan,
render_chan: RenderChan,
+ /// The most recently loaded url
+ url: Option<Url>,
}
impl Pipeline {
@@ -90,12 +93,24 @@ impl Pipeline {
script_chan: script_chan,
layout_chan: layout_chan,
render_chan: render_chan,
+ url: None,
+ }
+ }
+
+ pub fn load(&mut self, url: Url) {
+ self.url = Some(url.clone());
+ self.script_chan.send(LoadMsg(url));
+ }
+
+ pub fn reload(&self) {
+ for self.url.iter().advance |&url| {
+ self.script_chan.send(LoadMsg(url));
}
}
pub fn exit(&self) {
+ // Script task handles shutting down layout, as well
self.script_chan.send(script_task::ExitMsg);
- self.layout_chan.send(layout_interface::ExitMsg);
let (response_port, response_chan) = comm::stream();
self.render_chan.send(render_task::ExitMsg(response_chan));
diff --git a/src/components/main/platform/common/glut_windowing.rs b/src/components/main/platform/common/glut_windowing.rs
index a47fab68acc..da07fa99ef0 100644
--- a/src/components/main/platform/common/glut_windowing.rs
+++ b/src/components/main/platform/common/glut_windowing.rs
@@ -9,7 +9,7 @@
use windowing::{ApplicationMethods, CompositeCallback, LoadUrlCallback, MouseCallback};
use windowing::{ResizeCallback, ScrollCallback, WindowMethods, WindowMouseEvent, WindowClickEvent};
-use windowing::{WindowMouseDownEvent, WindowMouseUpEvent, ZoomCallback};
+use windowing::{WindowMouseDownEvent, WindowMouseUpEvent, ZoomCallback, Forward, Back, NavigationCallback};
use alert::{Alert, AlertMethods};
use std::libc::c_int;
@@ -17,7 +17,8 @@ use geom::point::Point2D;
use geom::size::Size2D;
use servo_msg::compositor::{IdleRenderState, RenderState, RenderingRenderState};
use servo_msg::compositor::{FinishedLoading, Loading, PerformingLayout, ReadyState};
-use glut::glut::{ACTIVE_CTRL, DOUBLE, HAVE_PRECISE_MOUSE_WHEEL, WindowHeight, WindowWidth};
+use glut::glut::{ACTIVE_CTRL, ACTIVE_SHIFT, DOUBLE, HAVE_PRECISE_MOUSE_WHEEL, WindowHeight};
+use glut::glut::WindowWidth;
use glut::glut;
use glut::machack;
@@ -44,6 +45,7 @@ pub struct Window {
mouse_callback: Option<MouseCallback>,
scroll_callback: Option<ScrollCallback>,
zoom_callback: Option<ZoomCallback>,
+ navigation_callback: Option<NavigationCallback>,
drag_origin: Point2D<c_int>,
@@ -72,6 +74,7 @@ impl WindowMethods<Application> for Window {
mouse_callback: None,
scroll_callback: None,
zoom_callback: None,
+ navigation_callback: None,
drag_origin: Point2D(0 as c_int, 0),
@@ -177,6 +180,11 @@ impl WindowMethods<Application> for Window {
self.zoom_callback = Some(new_zoom_callback)
}
+ /// Registers a callback to be run when backspace or shift-backspace is pressed.
+ pub fn set_navigation_callback(&mut self, new_navigation_callback: NavigationCallback) {
+ self.navigation_callback = Some(new_navigation_callback)
+ }
+
/// Spins the event loop.
pub fn check_loop(@mut self) {
glut::check_loop()
@@ -226,20 +234,33 @@ impl Window {
/// Helper function to handle keyboard events.
fn handle_key(&self, key: u8) {
- debug!("got key: %d", key as int);
+ debug!("got key: %?", key);
+ let modifiers = glut::get_modifiers();
match key {
- 12 => self.load_url(), // Ctrl+L
- k if k == ('=' as u8) && (glut::get_modifiers() & ACTIVE_CTRL) != 0 => { // Ctrl++
+ 12 => self.load_url(), // Ctrl+L
+ 31 if (modifiers & ACTIVE_CTRL) != 0 => { // Ctrl+-
for self.zoom_callback.iter().advance |&callback| {
- callback(0.1);
+ callback(-0.1);
}
}
- k if k == 31 && (glut::get_modifiers() & ACTIVE_CTRL) != 0 => { // Ctrl+-
- for self.zoom_callback.iter().advance |&callback| {
- callback(-0.1);
+ 127 => {
+ for self.navigation_callback.iter().advance |&callback| {
+ if (modifiers & ACTIVE_SHIFT) != 0 { // Shift+Backspace
+ callback(Forward);
+ }
+ else {
+ callback(Back);
+ }
+ }
+ }
+ c => match c as char {
+ '=' if (modifiers & ACTIVE_CTRL) != 0 => { // Ctrl++
+ for self.zoom_callback.iter().advance |&callback| {
+ callback(0.1);
+ }
}
+ _ => {}
}
- _ => {}
}
}
diff --git a/src/components/main/windowing.rs b/src/components/main/windowing.rs
index 56a6cbcb0ab..dc9f5472b6c 100644
--- a/src/components/main/windowing.rs
+++ b/src/components/main/windowing.rs
@@ -14,6 +14,11 @@ pub enum WindowMouseEvent {
WindowMouseUpEvent(uint, Point2D<f32>),
}
+pub enum WindowNavigateMsg {
+ Forward,
+ Back,
+}
+
/// Type of the function that is called when the screen is to be redisplayed.
pub type CompositeCallback = @fn();
@@ -29,9 +34,12 @@ pub type MouseCallback = @fn(WindowMouseEvent);
/// Type of the function that is called when the user scrolls.
pub type ScrollCallback = @fn(Point2D<f32>);
-///Type of the function that is called when the user zooms.
+/// Type of the function that is called when the user zooms.
pub type ZoomCallback = @fn(f32);
+/// Type of the function that is called when the user clicks backspace or shift-backspace
+pub type NavigationCallback = @fn(WindowNavigateMsg);
+
/// Methods for an abstract Application.
pub trait ApplicationMethods {
fn new() -> Self;
@@ -57,6 +65,8 @@ pub trait WindowMethods<A> {
pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback);
/// Registers a callback to run when the user zooms.
pub fn set_zoom_callback(&mut self, new_zoom_callback: ZoomCallback);
+ /// Registers a callback to run when the user presses backspace or shift-backspace.
+ pub fn set_navigation_callback(&mut self, new_navigation_callback: NavigationCallback);
/// Spins the event loop.
pub fn check_loop(@mut self);
diff --git a/src/components/msg/compositor.rs b/src/components/msg/compositor.rs
index 6d8fe2ecc50..d677cdfdaf1 100644
--- a/src/components/msg/compositor.rs
+++ b/src/components/msg/compositor.rs
@@ -8,6 +8,7 @@ use geom::rect::Rect;
use geom::size::Size2D;
use std::util::NonCopyable;
+#[deriving(Clone)]
pub struct LayerBuffer {
draw_target: DrawTarget,
@@ -23,6 +24,7 @@ pub struct LayerBuffer {
/// A set of layer buffers. This is an atomic unit used to switch between the front and back
/// buffers.
+#[deriving(Clone)]
pub struct LayerBufferSet {
buffers: ~[LayerBuffer]
}
diff --git a/src/components/msg/constellation.rs b/src/components/msg/constellation.rs
index b0b97ba528a..aa6442a525d 100644
--- a/src/components/msg/constellation.rs
+++ b/src/components/msg/constellation.rs
@@ -27,8 +27,13 @@ impl ConstellationChan {
pub enum Msg {
LoadUrlMsg(Url),
+ NavigateMsg(NavigationDirection),
ExitMsg(Chan<()>),
RendererReadyMsg(uint),
TokenSurrenderMsg(~CompositorToken),
}
+pub enum NavigationDirection {
+ Forward,
+ Back,
+}
diff --git a/src/components/script/dom/characterdata.rs b/src/components/script/dom/characterdata.rs
index 91838432f6b..9d77d3b64ee 100644
--- a/src/components/script/dom/characterdata.rs
+++ b/src/components/script/dom/characterdata.rs
@@ -7,8 +7,6 @@
use dom::bindings::utils::{DOMString, null_string, str};
use dom::node::{Node, NodeTypeId, ScriptView};
-use std::str;
-
pub struct CharacterData {
parent: Node<ScriptView>,
data: DOMString
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs
index d415288bfa2..c573f9912fb 100644
--- a/src/components/script/dom/node.rs
+++ b/src/components/script/dom/node.rs
@@ -367,7 +367,7 @@ impl<View> AbstractNode<View> {
pub fn dump_indent(&self, indent: uint) {
let mut s = ~"";
for uint::range(0u, indent) |_i| {
- s += ~" ";
+ s += " ";
}
s += self.debug_str();
diff --git a/src/components/script/html/cssparse.rs b/src/components/script/html/cssparse.rs
index 1278ba47f6c..95a600682ac 100644
--- a/src/components/script/html/cssparse.rs
+++ b/src/components/script/html/cssparse.rs
@@ -8,7 +8,6 @@ use std::cell::Cell;
use std::comm;
use std::comm::Port;
use std::task;
-use std::str;
use newcss::stylesheet::Stylesheet;
use newcss::util::DataStream;
use servo_net::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs
index 00b5611caba..8acee44e891 100644
--- a/src/components/script/script_task.rs
+++ b/src/components/script/script_task.rs
@@ -19,7 +19,9 @@ use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg, Reflo
use layout_interface::{ReflowDocumentDamage, ReflowForDisplay, ReflowForScriptQuery, ReflowGoal};
use layout_interface::ReflowMsg;
use layout_interface;
-use servo_msg::constellation::{ConstellationChan, LoadUrlMsg, RendererReadyMsg};
+use servo_msg::constellation::{ConstellationChan, LoadUrlMsg, NavigationDirection};
+use servo_msg::constellation::RendererReadyMsg;
+use servo_msg::constellation;
use std::cast::transmute;
use std::cell::Cell;
@@ -53,6 +55,8 @@ pub enum ScriptMsg {
LoadMsg(Url),
/// Executes a standalone script.
ExecuteMsg(Url),
+ /// Instructs the script task to send a navigate message to the constellation.
+ NavigateMsg(NavigationDirection),
/// Sends a DOM event.
SendEventMsg(Event),
/// Fires a JavaScript timeout.
@@ -136,6 +140,11 @@ pub struct ScriptTask {
window_size: Size2D<uint>,
/// What parts of the document are dirty, if any.
damage: Option<DocumentDamage>,
+
+ /// Cached copy of the most recent url loaded by the script
+ /// TODO(tkuehn): this currently does not follow any particular caching policy
+ /// and simply caches pages forever (!).
+ last_loaded_url: Option<Url>,
}
fn global_script_context_key(_: @ScriptTask) {}
@@ -212,6 +221,8 @@ impl ScriptTask {
window_size: Size2D(800u, 600),
damage: None,
+
+ last_loaded_url: None,
};
// Indirection for Rust Issue #6248, dynamic freeze scope artifically extended
let script_task_ptr = {
@@ -264,31 +275,18 @@ impl ScriptTask {
/// Handles an incoming control message.
fn handle_msg(&mut self) -> bool {
match self.script_port.recv() {
- LoadMsg(url) => {
- self.load(url);
- true
- }
- ExecuteMsg(url) => {
- self.handle_execute_msg(url);
- true
- }
- SendEventMsg(event) => {
- self.handle_event(event);
- true
- }
- FireTimerMsg(timer_data) => {
- self.handle_fire_timer_msg(timer_data);
- true
- }
- ReflowCompleteMsg => {
- self.handle_reflow_complete_msg();
- true
- }
+ LoadMsg(url) => self.load(url),
+ ExecuteMsg(url) => self.handle_execute_msg(url),
+ SendEventMsg(event) => self.handle_event(event),
+ FireTimerMsg(timer_data) => self.handle_fire_timer_msg(timer_data),
+ NavigateMsg(direction) => self.handle_navigate_msg(direction),
+ ReflowCompleteMsg => self.handle_reflow_complete_msg(),
ExitMsg => {
self.handle_exit_msg();
- false
+ return false
}
}
+ true
}
/// Handles a request to execute a script.
@@ -337,6 +335,11 @@ impl ScriptTask {
self.compositor.set_ready_state(FinishedLoading);
}
+ /// Handles a navigate forward or backward message.
+ fn handle_navigate_msg(&self, direction: NavigationDirection) {
+ self.constellation_chan.send(constellation::NavigateMsg(direction));
+ }
+
/// Handles a request to exit the script task and shut down layout.
fn handle_exit_msg(&mut self) {
self.join_layout();
@@ -350,6 +353,9 @@ impl ScriptTask {
/// The entry point to document loading. Defines bindings, sets up the window and document
/// objects, parses HTML and CSS, and kicks off initial layout.
fn load(&mut self, url: Url) {
+ for self.last_loaded_url.iter().advance |&last_loaded_url| {
+ if url == last_loaded_url { return; }
+ }
// Define the script DOM bindings.
//
// FIXME: Can this be done earlier, to save the flag?
@@ -362,7 +368,7 @@ impl ScriptTask {
// Parse HTML.
//
// Note: We can parse the next document in parallel with any previous documents.
- let html_parsing_result = hubbub_html_parser::parse_html(copy url,
+ let html_parsing_result = hubbub_html_parser::parse_html(url.clone(),
self.resource_task.clone(),
self.image_cache_task.clone());
@@ -396,7 +402,7 @@ impl ScriptTask {
self.root_frame = Some(Frame {
document: document,
window: window,
- url: url
+ url: url.clone(),
});
// Perform the initial reflow.
@@ -416,6 +422,7 @@ impl ScriptTask {
~"???",
1);
}
+ self.last_loaded_url = Some(url);
}
/// Sends a ping to layout and waits for the response. The response will arrive when the
diff --git a/src/components/util/time.rs b/src/components/util/time.rs
index 00e222baaeb..ac94abcfb7a 100644
--- a/src/components/util/time.rs
+++ b/src/components/util/time.rs
@@ -152,7 +152,7 @@ impl Profiler {
priv fn print_buckets(&mut self) {
println(fmt!("%31s %15s %15s %15s %15s %15s",
- "_category (ms)_", "_mean (ms)_", "_median (ms)_",
+ "_category_", "_mean (ms)_", "_median (ms)_",
"_min (ms)_", "_max (ms)_", "_bucket size_"));
for self.buckets.mut_iter().advance |bucket| {
match *bucket {
diff --git a/src/support/alert/rust-alert b/src/support/alert/rust-alert
-Subproject 502ec156da38860a4dff911cf8f33f388a0a188
+Subproject 68875af396cb583e670dd5caad99431dac62f8d