aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2014-11-24 17:23:30 -0800
committerPatrick Walton <pcwalton@mimiga.net>2014-12-10 08:35:47 -0800
commit8b2aadc30be9e7da163b0eb5b88f2988f5b43f9e (patch)
tree722684b4013644a1ccc3d635f45f3521dd66dc08 /components
parent315e166cf7f24f4586e8ce863be597ce0a3f34c9 (diff)
downloadservo-8b2aadc30be9e7da163b0eb5b88f2988f5b43f9e.tar.gz
servo-8b2aadc30be9e7da163b0eb5b88f2988f5b43f9e.zip
ports/cef: Implement accelerated compositing for the CEF port.
Diffstat (limited to 'components')
-rw-r--r--components/compositing/compositor.rs104
-rw-r--r--components/compositing/compositor_task.rs22
-rw-r--r--components/compositing/constellation.rs185
-rw-r--r--components/compositing/headless.rs12
-rw-r--r--components/compositing/pipeline.rs35
-rw-r--r--components/compositing/windowing.rs25
-rw-r--r--components/msg/compositor_msg.rs4
-rw-r--r--components/msg/constellation_msg.rs3
-rw-r--r--components/script/dom/document.rs8
-rw-r--r--components/script/dom/htmltitleelement.rs22
-rw-r--r--components/script/dom/virtualmethods.rs8
-rw-r--r--components/script/page.rs17
-rw-r--r--components/script/script_task.rs17
-rw-r--r--components/script_traits/lib.rs3
-rw-r--r--components/servo/Cargo.lock4
-rw-r--r--components/servo/lib.rs8
-rw-r--r--components/servo/main.rs6
17 files changed, 359 insertions, 124 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index 44015c8012c..c5a11fa1605 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -3,23 +3,23 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use compositor_layer::{CompositorData, CompositorLayer, DoesntWantScrollEvents};
-use compositor_layer::WantsScrollEvents;
-use compositor_task::{ChangeReadyState, ChangePaintState, CompositorEventListener};
-use compositor_task::{CompositorProxy, CompositorReceiver, CompositorTask};
-use compositor_task::{CreateOrUpdateDescendantLayer, CreateOrUpdateRootLayer, Exit};
-use compositor_task::{FrameTreeUpdateMsg, GetGraphicsMetadata, LayerProperties};
+use compositor_layer::{WantsScrollEvents};
+use compositor_task::{ChangePageLoadData, ChangePageTitle, ChangePaintState, ChangeReadyState};
+use compositor_task::{CompositorEventListener, CompositorProxy, CompositorReceiver};
+use compositor_task::{CompositorTask, CreateOrUpdateDescendantLayer, CreateOrUpdateRootLayer};
+use compositor_task::{Exit, FrameTreeUpdateMsg, GetGraphicsMetadata, LayerProperties};
use compositor_task::{LoadComplete, Msg, Paint, PaintMsgDiscarded, ScrollFragmentPoint};
use compositor_task::{ScrollTimeout, SetIds, SetLayerOrigin, ShutdownComplete};
-use constellation::{SendableFrameTree, FrameTreeDiff};
+use constellation::{FrameId, FrameTreeDiff, SendableFrameTree};
use pipeline::CompositionPipeline;
use scrolling::ScrollingTimerProxy;
use windowing;
-use windowing::{IdleWindowEvent, LoadUrlWindowEvent, MouseWindowClickEvent};
-use windowing::{MouseWindowEvent, MouseWindowEventClass, MouseWindowMouseDownEvent};
-use windowing::{MouseWindowMouseUpEvent, MouseWindowMoveEventClass, NavigationWindowEvent};
+use windowing::{IdleWindowEvent, InitializeCompositingWindowEvent};
+use windowing::{KeyEvent, LoadUrlWindowEvent, MouseWindowClickEvent, MouseWindowEvent};
+use windowing::{MouseWindowEventClass, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
+use windowing::{MouseWindowMoveEventClass, NavigationWindowEvent, PinchZoomWindowEvent};
use windowing::{QuitWindowEvent, RefreshWindowEvent, ResizeWindowEvent, ScrollWindowEvent};
use windowing::{WindowEvent, WindowMethods, WindowNavigateMsg, ZoomWindowEvent};
-use windowing::{PinchZoomWindowEvent, KeyEvent};
use azure::azure_hl;
use std::cmp;
@@ -40,11 +40,11 @@ use gleam::gl::types::{GLint, GLsizei};
use gleam::gl;
use script_traits::{ViewportMsg, ScriptControlChan};
use servo_msg::compositor_msg::{Blank, Epoch, FinishedLoading, IdlePaintState, LayerId};
-use servo_msg::compositor_msg::{ReadyState, PaintingPaintState, PaintState, Scrollable};
-use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, LoadUrlMsg};
-use servo_msg::constellation_msg::{NavigateMsg, LoadData, PipelineId, ResizedWindowMsg};
-use servo_msg::constellation_msg::{WindowSizeData, KeyState, Key, KeyModifiers};
-use servo_msg::constellation_msg;
+use servo_msg::compositor_msg::{ReadyState, PaintState, PaintingPaintState, Scrollable};
+use servo_msg::constellation_msg::{mod, ConstellationChan, ExitMsg};
+use servo_msg::constellation_msg::{GetPipelineTitleMsg, Key, KeyModifiers, KeyState, LoadData};
+use servo_msg::constellation_msg::{LoadUrlMsg, NavigateMsg, PipelineId, ResizedWindowMsg};
+use servo_msg::constellation_msg::{WindowSizeData};
use servo_util::geometry::{PagePx, ScreenPx, ViewportPx};
use servo_util::memory::MemoryProfilerChan;
use servo_util::opts;
@@ -58,6 +58,7 @@ use std::slice::bytes::copy_memory;
use time::{precise_time_ns, precise_time_s};
use url::Url;
+/// NB: Never block on the constellation, because sometimes the constellation blocks on us.
pub struct IOCompositor<Window: WindowMethods> {
/// The application window.
window: Rc<Window>,
@@ -65,8 +66,9 @@ pub struct IOCompositor<Window: WindowMethods> {
/// The port on which we receive messages.
port: Box<CompositorReceiver>,
- /// The render context.
- context: RenderContext,
+ /// The render context. This will be `None` if the windowing system has not yet sent us a
+ /// `PrepareRenderingEvent`.
+ context: Option<RenderContext>,
/// The root pipeline.
root_pipeline: Option<CompositionPipeline>,
@@ -177,13 +179,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
// display list. This is only here because we don't have that logic in the painter yet.
let window_size = window.framebuffer_size();
let hidpi_factor = window.hidpi_factor();
- let context = CompositorTask::create_graphics_context(&window.native_metadata());
-
- let show_debug_borders = opts::get().show_debug_borders;
IOCompositor {
window: window,
port: receiver,
- context: rendergl::RenderContext::new(context, show_debug_borders),
+ context: None,
root_pipeline: None,
scene: Scene::new(Rect {
origin: Zero::zero(),
@@ -262,6 +261,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.change_paint_state(pipeline_id, paint_state);
}
+ (ChangePageTitle(pipeline_id, title), NotShuttingDown) => {
+ self.change_page_title(pipeline_id, title);
+ }
+
+ (ChangePageLoadData(frame_id, load_data), NotShuttingDown) => {
+ self.change_page_load_data(frame_id, load_data);
+ }
+
(PaintMsgDiscarded, NotShuttingDown) => {
self.remove_outstanding_paint_msg();
}
@@ -305,13 +312,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.scroll_fragment_to_point(pipeline_id, layer_id, point);
}
- (LoadComplete(..), NotShuttingDown) => {
+ (LoadComplete, NotShuttingDown) => {
self.got_load_complete_message = true;
// If we're painting in headless mode, schedule a recomposite.
if opts::get().output_file.is_some() {
self.composite_if_necessary();
}
+
+ // Inform the embedder that the load has finished.
+ //
+ // TODO(pcwalton): Specify which frame's load completed.
+ self.window.load_end();
}
(ScrollTimeout(timestamp), NotShuttingDown) => {
@@ -371,6 +383,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.window.set_paint_state(paint_state);
}
+ fn change_page_title(&mut self, _: PipelineId, title: Option<String>) {
+ self.window.set_page_title(title);
+ }
+
+ fn change_page_load_data(&mut self, _: FrameId, load_data: LoadData) {
+ self.window.set_page_load_data(load_data);
+ }
+
fn all_pipelines_in_idle_paint_state(&self) -> bool {
if self.ready_states.len() == 0 {
return false;
@@ -629,7 +649,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
IdleWindowEvent => {}
RefreshWindowEvent => {
- self.composite_if_necessary()
+ self.composite();
+ }
+
+ InitializeCompositingWindowEvent => {
+ self.initialize_compositing();
}
ResizeWindowEvent(size) => {
@@ -678,6 +702,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
fn on_resize_window_event(&mut self, new_size: TypedSize2D<DevicePixel, uint>) {
+ debug!("compositor resizing to {}", new_size.to_untyped());
+
// A size change could also mean a resolution change.
let new_hidpi_factor = self.window.hidpi_factor();
if self.hidpi_factor != new_hidpi_factor {
@@ -960,6 +986,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
fn composite(&mut self) {
+ if !self.window.prepare_for_composite() {
+ return
+ }
+
let output_image = opts::get().output_file.is_some() &&
self.is_ready_to_paint_image_output();
@@ -995,7 +1025,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
// paint the scene.
match self.scene.root {
Some(ref layer) => {
- rendergl::render_scene(layer.clone(), self.context, &self.scene);
+ match self.context {
+ None => {
+ debug!("compositor: not compositing because context not yet set up")
+ }
+ Some(context) => {
+ rendergl::render_scene(layer.clone(), context, &self.scene);
+ }
+ }
}
None => {}
}
@@ -1053,6 +1090,12 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}
+ fn initialize_compositing(&mut self) {
+ let context = CompositorTask::create_graphics_context(&self.window.native_metadata());
+ let show_debug_borders = opts::get().show_debug_borders;
+ self.context = Some(rendergl::RenderContext::new(context, show_debug_borders))
+ }
+
fn find_topmost_layer_at_point_for_layer(&self,
layer: Rc<Layer<CompositorData>>,
point: TypedPoint2D<LayerPixel, f32>)
@@ -1229,4 +1272,17 @@ impl<Window> CompositorEventListener for IOCompositor<Window> where Window: Wind
self.scrolling_timer.shutdown();
}
+
+ fn pinch_zoom_level(&self) -> f32 {
+ self.viewport_zoom.get() as f32
+ }
+
+ fn get_title_for_main_frame(&self) {
+ let root_pipeline_id = match self.root_pipeline {
+ None => return,
+ Some(ref root_pipeline) => root_pipeline.id,
+ };
+ let ConstellationChan(ref chan) = self.constellation_chan;
+ chan.send(GetPipelineTitleMsg(root_pipeline_id));
+ }
}
diff --git a/components/compositing/compositor_task.rs b/components/compositing/compositor_task.rs
index 89aed5defa0..e7d851ceaf6 100644
--- a/components/compositing/compositor_task.rs
+++ b/components/compositing/compositor_task.rs
@@ -5,7 +5,7 @@
//! Communication with the compositor task.
pub use windowing;
-pub use constellation::{SendableFrameTree, FrameTreeDiff};
+pub use constellation::{FrameId, SendableFrameTree, FrameTreeDiff};
use compositor;
use headless;
@@ -19,7 +19,7 @@ use layers::platform::surface::{NativeCompositingGraphicsContext, NativeGraphics
use layers::layers::LayerBufferSet;
use servo_msg::compositor_msg::{Epoch, LayerId, LayerMetadata, ReadyState};
use servo_msg::compositor_msg::{PaintListener, PaintState, ScriptListener, ScrollPolicy};
-use servo_msg::constellation_msg::{ConstellationChan, PipelineId};
+use servo_msg::constellation_msg::{ConstellationChan, LoadData, PipelineId};
use servo_util::memory::MemoryProfilerChan;
use servo_util::time::TimeProfilerChan;
use std::comm::{channel, Sender, Receiver};
@@ -81,8 +81,13 @@ impl ScriptListener for Box<CompositorProxy+'static+Send> {
fn dup(&mut self) -> Box<ScriptListener+'static> {
box self.clone_compositor_proxy() as Box<ScriptListener+'static>
}
+
+ fn set_title(&mut self, pipeline_id: PipelineId, title: Option<String>) {
+ self.send(ChangePageTitle(pipeline_id, title))
+ }
}
+/// Information about each layer that the compositor keeps.
pub struct LayerProperties {
pub pipeline_id: PipelineId,
pub epoch: Epoch,
@@ -184,9 +189,13 @@ pub enum Msg {
ChangeReadyState(PipelineId, ReadyState),
/// Alerts the compositor to the current status of painting.
ChangePaintState(PipelineId, PaintState),
- /// Alerts the compositor that the PaintMsg has been discarded.
+ /// Alerts the compositor that the current page has changed its title.
+ ChangePageTitle(PipelineId, Option<String>),
+ /// Alerts the compositor that the current page has changed its load data (including URL).
+ ChangePageLoadData(FrameId, LoadData),
+ /// Alerts the compositor that a `PaintMsg` has been discarded.
PaintMsgDiscarded,
- /// Sets the channel to the current layout and paint tasks, along with their id
+ /// Sets the channel to the current layout and paint tasks, along with their ID.
SetIds(SendableFrameTree, Sender<()>, ConstellationChan),
/// Sends an updated version of the frame tree.
FrameTreeUpdateMsg(FrameTreeDiff, Sender<()>),
@@ -210,6 +219,8 @@ impl Show for Msg {
Paint(..) => write!(f, "Paint"),
ChangeReadyState(..) => write!(f, "ChangeReadyState"),
ChangePaintState(..) => write!(f, "ChangePaintState"),
+ ChangePageTitle(..) => write!(f, "ChangePageTitle"),
+ ChangePageLoadData(..) => write!(f, "ChangePageLoadData"),
PaintMsgDiscarded(..) => write!(f, "PaintMsgDiscarded"),
SetIds(..) => write!(f, "SetIds"),
FrameTreeUpdateMsg(..) => write!(f, "FrameTreeUpdateMsg"),
@@ -269,5 +280,8 @@ pub trait CompositorEventListener {
fn handle_event(&mut self, event: WindowEvent) -> bool;
fn repaint_synchronously(&mut self);
fn shutdown(&mut self);
+ fn pinch_zoom_level(&self) -> f32;
+ /// Requests that the compositor send the title for the main frame as soon as possible.
+ fn get_title_for_main_frame(&self);
}
diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs
index 5155801f553..a993394de13 100644
--- a/components/compositing/constellation.rs
+++ b/components/compositing/constellation.rs
@@ -4,7 +4,8 @@
use pipeline::{Pipeline, CompositionPipeline};
-use compositor_task::{CompositorProxy, FrameTreeUpdateMsg, LoadComplete, ShutdownComplete, SetLayerOrigin, SetIds};
+use compositor_task::{ChangePageLoadData, ChangePageTitle, CompositorProxy, FrameTreeUpdateMsg};
+use compositor_task::{LoadComplete, SetLayerOrigin, SetIds, ShutdownComplete};
use devtools_traits;
use devtools_traits::DevtoolsControlChan;
use geom::rect::{Rect, TypedRect};
@@ -14,16 +15,16 @@ use gfx::paint_task;
use layers::geometry::DevicePixel;
use layout_traits::{LayoutControlChan, LayoutTaskFactory, ExitNowMsg};
use libc;
-use script_traits;
-use script_traits::{ResizeMsg, ResizeInactiveMsg, ExitPipelineMsg, SendEventMsg};
+use script_traits::{mod, GetTitleMsg, ResizeMsg, ResizeInactiveMsg, ExitPipelineMsg, SendEventMsg};
use script_traits::{ScriptControlChan, ScriptTaskFactory};
use servo_msg::compositor_msg::LayerId;
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, Failure, FrameRectMsg};
+use servo_msg::constellation_msg::{GetPipelineTitleMsg};
use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
-use servo_msg::constellation_msg::{LoadCompleteMsg, LoadUrlMsg, LoadData, Msg, NavigateMsg};
-use servo_msg::constellation_msg::{NavigationType, PipelineId, PainterReadyMsg, ResizedWindowMsg};
+use servo_msg::constellation_msg::{KeyEvent, Key, KeyState, KeyModifiers, LoadCompleteMsg};
+use servo_msg::constellation_msg::{LoadData, LoadUrlMsg, Msg, NavigateMsg, NavigationType};
+use servo_msg::constellation_msg::{PainterReadyMsg, PipelineId, ResizedWindowMsg};
use servo_msg::constellation_msg::{ScriptLoadedURLInIFrameMsg, SubpageId, WindowSizeData};
-use servo_msg::constellation_msg::{KeyEvent, Key, KeyState, KeyModifiers};
use servo_msg::constellation_msg;
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
use servo_net::resource_task::ResourceTask;
@@ -76,6 +77,10 @@ pub struct Constellation<LTF, STF> {
/// The next free ID to assign to a pipeline.
next_pipeline_id: PipelineId,
+ /// The next free ID to assign to a frame.
+ next_frame_id: FrameId,
+
+ /// Navigation operations that are in progress.
pending_frames: Vec<FrameChange>,
pending_sizes: HashMap<(PipelineId, SubpageId), TypedRect<PagePx, f32>>,
@@ -86,17 +91,28 @@ pub struct Constellation<LTF, STF> {
pub window_size: WindowSizeData,
}
-/// Stores the Id of the outermost frame's pipeline, along with a vector of children frames
+/// A unique ID used to identify a frame.
+pub struct FrameId(u32);
+
+/// One frame in the hierarchy.
struct FrameTree {
+ /// The ID of this frame.
+ pub id: FrameId,
+ /// The pipeline for this frame.
pub pipeline: Rc<Pipeline>,
+ /// The parent frame's pipeline.
pub parent: RefCell<Option<Rc<Pipeline>>>,
+ /// A vector of child frames.
pub children: RefCell<Vec<ChildFrameTree>>,
+ /// Whether this frame has a compositor layer.
pub has_compositor_layer: Cell<bool>,
}
impl FrameTree {
- fn new(pipeline: Rc<Pipeline>, parent_pipeline: Option<Rc<Pipeline>>) -> FrameTree {
+ fn new(id: FrameId, pipeline: Rc<Pipeline>, parent_pipeline: Option<Rc<Pipeline>>)
+ -> FrameTree {
FrameTree {
+ id: id,
pipeline: pipeline,
parent: RefCell::new(parent_pipeline),
children: RefCell::new(vec!()),
@@ -234,16 +250,19 @@ impl Iterator<Rc<FrameTree>> for FrameTreeIterator {
/// Represents the portion of a page that is changing in navigating.
struct FrameChange {
+ /// The old pipeline ID.
pub before: Option<PipelineId>,
+ /// The resulting frame tree after navigation.
pub after: Rc<FrameTree>,
+ /// The kind of navigation that is occurring.
pub navigation_type: NavigationType,
}
/// Stores the Id's of the pipelines previous and next in the browser's history
struct NavigationContext {
- pub previous: Vec<Rc<FrameTree>>,
- pub next: Vec<Rc<FrameTree>>,
- pub current: Option<Rc<FrameTree>>,
+ previous: Vec<Rc<FrameTree>>,
+ next: Vec<Rc<FrameTree>>,
+ current: Option<Rc<FrameTree>>,
}
impl NavigationContext {
@@ -258,29 +277,30 @@ impl NavigationContext {
/* Note that the following two methods can fail. They should only be called *
* when it is known that there exists either a previous page or a next page. */
- fn back(&mut self) -> Rc<FrameTree> {
+ fn back(&mut self, compositor_proxy: &mut CompositorProxy) -> Rc<FrameTree> {
self.next.push(self.current.take().unwrap());
let prev = self.previous.pop().unwrap();
- self.current = Some(prev.clone());
+ self.set_current(prev.clone(), compositor_proxy);
prev
}
- fn forward(&mut self) -> Rc<FrameTree> {
+ fn forward(&mut self, compositor_proxy: &mut CompositorProxy) -> Rc<FrameTree> {
self.previous.push(self.current.take().unwrap());
let next = self.next.pop().unwrap();
- self.current = Some(next.clone());
+ self.set_current(next.clone(), compositor_proxy);
next
}
/// Loads a new set of page frames, returning all evicted frame trees
- fn load(&mut self, frame_tree: Rc<FrameTree>) -> Vec<Rc<FrameTree>> {
+ fn load(&mut self, frame_tree: Rc<FrameTree>, compositor_proxy: &mut CompositorProxy)
+ -> Vec<Rc<FrameTree>> {
debug!("navigating to {}", frame_tree.pipeline.id);
let evicted = replace(&mut self.next, vec!());
match self.current.take() {
Some(current) => self.previous.push(current),
None => (),
}
- self.current = Some(frame_tree);
+ self.set_current(frame_tree, compositor_proxy);
evicted
}
@@ -308,6 +328,14 @@ impl NavigationContext {
frame_tree.contains(pipeline_id)
})
}
+
+ /// Always use this method to set the currently-displayed frame. It correctly informs the
+ /// compositor of the new URLs.
+ fn set_current(&mut self, new_frame: Rc<FrameTree>, compositor_proxy: &mut CompositorProxy) {
+ self.current = Some(new_frame.clone());
+ compositor_proxy.send(ChangePageLoadData(new_frame.id,
+ new_frame.pipeline.load_data.clone()));
+ }
}
impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
@@ -334,6 +362,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
pipelines: HashMap::new(),
navigation_context: NavigationContext::new(),
next_pipeline_id: PipelineId(0),
+ next_frame_id: FrameId(0),
pending_frames: vec!(),
pending_sizes: HashMap::new(),
time_profiler_chan: time_profiler_chan,
@@ -358,31 +387,30 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
}
/// Helper function for creating a pipeline
- fn new_pipeline(&self,
+ fn new_pipeline(&mut self,
id: PipelineId,
subpage_id: Option<SubpageId>,
script_pipeline: Option<Rc<Pipeline>>,
load_data: LoadData)
-> Rc<Pipeline> {
- let pipe = Pipeline::create::<LTF, STF>(id,
- subpage_id,
- self.chan.clone(),
- self.compositor_proxy.clone_compositor_proxy(),
- self.devtools_chan.clone(),
- self.image_cache_task.clone(),
- self.font_cache_task.clone(),
- self.resource_task.clone(),
- self.storage_task.clone(),
- self.time_profiler_chan.clone(),
- self.window_size,
- script_pipeline,
- load_data);
- pipe.load();
- Rc::new(pipe)
- }
-
-
- /// Helper function for getting a unique pipeline Id
+ let pipe = Pipeline::create::<LTF, STF>(id,
+ subpage_id,
+ self.chan.clone(),
+ self.compositor_proxy.clone_compositor_proxy(),
+ self.devtools_chan.clone(),
+ self.image_cache_task.clone(),
+ self.font_cache_task.clone(),
+ self.resource_task.clone(),
+ self.storage_task.clone(),
+ self.time_profiler_chan.clone(),
+ self.window_size,
+ script_pipeline,
+ load_data.clone());
+ pipe.load();
+ Rc::new(pipe)
+ }
+
+ /// Helper function for getting a unique pipeline ID.
fn get_next_pipeline_id(&mut self) -> PipelineId {
let id = self.next_pipeline_id;
let PipelineId(ref mut i) = self.next_pipeline_id;
@@ -390,6 +418,14 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
id
}
+ /// Helper function for getting a unique frame ID.
+ fn get_next_frame_id(&mut self) -> FrameId {
+ let id = self.next_frame_id;
+ let FrameId(ref mut i) = self.next_frame_id;
+ *i += 1;
+ id
+ }
+
/// Convenience function for getting the currently active frame tree.
/// The currently active frame tree should always be the current painter
fn current_frame<'a>(&'a self) -> &'a Option<Rc<FrameTree>> {
@@ -465,6 +501,10 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
debug!("constellation got key event message");
self.handle_key_msg(key, state, modifiers);
}
+ GetPipelineTitleMsg(pipeline_id) => {
+ debug!("constellation got get-pipeline-title message");
+ self.handle_get_pipeline_title_msg(pipeline_id);
+ }
}
true
}
@@ -529,27 +569,38 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
debug!("creating replacement pipeline for about:failure");
let new_id = self.get_next_pipeline_id();
+ let new_frame_id = self.get_next_frame_id();
let pipeline = self.new_pipeline(new_id, subpage_id, None,
LoadData::new(Url::parse("about:failure").unwrap()));
- self.pending_frames.push(FrameChange{
- before: Some(pipeline_id),
- after: Rc::new(FrameTree::new(pipeline.clone(), None)),
- navigation_type: constellation_msg::Load,
- });
+ self.browse(Some(pipeline_id),
+ Rc::new(FrameTree::new(new_frame_id, pipeline.clone(), None)),
+ constellation_msg::Load);
self.pipelines.insert(new_id, pipeline);
}
+ /// Performs navigation. This pushes a `FrameChange` object onto the list of pending frames.
+ ///
+ /// TODO(pcwalton): Send a `BeforeBrowse` message to the embedder and allow cancellation.
+ fn browse(&mut self,
+ before: Option<PipelineId>,
+ after: Rc<FrameTree>,
+ navigation_type: NavigationType) {
+ self.pending_frames.push(FrameChange {
+ before: before,
+ after: after,
+ navigation_type: navigation_type,
+ });
+ }
+
fn handle_init_load(&mut self, url: Url) {
let next_pipeline_id = self.get_next_pipeline_id();
+ let next_frame_id = self.get_next_frame_id();
let pipeline = self.new_pipeline(next_pipeline_id, None, None, LoadData::new(url));
-
- self.pending_frames.push(FrameChange {
- before: None,
- after: Rc::new(FrameTree::new(pipeline.clone(), None)),
- navigation_type: constellation_msg::Load,
- });
+ self.browse(None,
+ Rc::new(FrameTree::new(next_frame_id, pipeline.clone(), None)),
+ constellation_msg::Load);
self.pipelines.insert(pipeline.id, pipeline);
}
@@ -690,15 +741,19 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
let rect = self.pending_sizes.remove(&(source_pipeline_id, subpage_id));
for frame_tree in frame_trees.iter() {
+ let next_frame_id = self.get_next_frame_id();
frame_tree.children.borrow_mut().push(ChildFrameTree::new(
- Rc::new(FrameTree::new(pipeline.clone(), Some(source_pipeline.clone()))),
+ Rc::new(FrameTree::new(next_frame_id,
+ pipeline.clone(),
+ Some(source_pipeline.clone()))),
rect));
}
self.pipelines.insert(pipeline.id, pipeline);
}
fn handle_load_url_msg(&mut self, source_id: PipelineId, load_data: LoadData) {
- debug!("Constellation: received message to load {:s}", load_data.url.to_string());
+ let url = load_data.url.to_string();
+ debug!("Constellation: received message to load {:s}", url);
// Make sure no pending page would be overridden.
let source_frame = self.current_frame().as_ref().unwrap().find(source_id).expect(
"Constellation: received a LoadUrlMsg from a pipeline_id associated
@@ -723,14 +778,13 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
let parent = source_frame.parent.clone();
let subpage_id = source_frame.pipeline.subpage_id;
let next_pipeline_id = self.get_next_pipeline_id();
-
+ let next_frame_id = self.get_next_frame_id();
let pipeline = self.new_pipeline(next_pipeline_id, subpage_id, None, load_data);
-
- self.pending_frames.push(FrameChange {
- before: Some(source_id),
- after: Rc::new(FrameTree::new(pipeline.clone(), parent.borrow().clone())),
- navigation_type: constellation_msg::Load,
- });
+ self.browse(Some(source_id),
+ Rc::new(FrameTree::new(next_frame_id,
+ pipeline.clone(),
+ parent.borrow().clone())),
+ constellation_msg::Load);
self.pipelines.insert(pipeline.id, pipeline);
}
@@ -752,7 +806,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
frame.pipeline.revoke_paint_permission();
}
}
- self.navigation_context.forward()
+ self.navigation_context.forward(&mut *self.compositor_proxy)
}
constellation_msg::Back => {
if self.navigation_context.previous.is_empty() {
@@ -764,7 +818,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
frame.pipeline.revoke_paint_permission();
}
}
- self.navigation_context.back()
+ self.navigation_context.back(&mut *self.compositor_proxy)
}
};
@@ -787,6 +841,16 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
});
}
+ fn handle_get_pipeline_title_msg(&mut self, pipeline_id: PipelineId) {
+ match self.pipelines.get(&pipeline_id) {
+ None => self.compositor_proxy.send(ChangePageTitle(pipeline_id, None)),
+ Some(pipeline) => {
+ let ScriptControlChan(ref script_channel) = pipeline.script_chan;
+ script_channel.send(GetTitleMsg(pipeline_id));
+ }
+ }
+ }
+
fn handle_painter_ready_msg(&mut self, pipeline_id: PipelineId) {
debug!("Painter {} ready to send paint msg", pipeline_id);
// This message could originate from a pipeline in the navigation context or
@@ -941,7 +1005,8 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
match navigation_type {
constellation_msg::Load => {
debug!("evicting old frames due to load");
- let evicted = self.navigation_context.load(frame_tree);
+ let evicted = self.navigation_context.load(frame_tree,
+ &mut *self.compositor_proxy);
self.handle_evicted_frames(evicted);
}
_ => {
diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs
index 459af00fcc2..7fc1df7dbe6 100644
--- a/components/compositing/headless.rs
+++ b/components/compositing/headless.rs
@@ -5,7 +5,8 @@
use compositor_task::{GetGraphicsMetadata, CreateOrUpdateRootLayer, CreateOrUpdateDescendantLayer};
use compositor_task::{Exit, ChangeReadyState, LoadComplete, Paint, ScrollFragmentPoint, SetIds};
use compositor_task::{SetLayerOrigin, ShutdownComplete, ChangePaintState, PaintMsgDiscarded};
-use compositor_task::{CompositorEventListener, CompositorReceiver, ScrollTimeout, FrameTreeUpdateMsg};
+use compositor_task::{CompositorEventListener, CompositorReceiver, ScrollTimeout, ChangePageTitle};
+use compositor_task::{ChangePageLoadData, FrameTreeUpdateMsg};
use windowing::WindowEvent;
use geom::scale_factor::ScaleFactor;
@@ -104,7 +105,8 @@ impl CompositorEventListener for NullCompositor {
CreateOrUpdateDescendantLayer(..) |
SetLayerOrigin(..) | Paint(..) |
ChangeReadyState(..) | ChangePaintState(..) | ScrollFragmentPoint(..) |
- LoadComplete | PaintMsgDiscarded(..) | ScrollTimeout(..) => ()
+ LoadComplete | PaintMsgDiscarded(..) | ScrollTimeout(..) | ChangePageTitle(..) |
+ ChangePageLoadData(..) => ()
}
true
}
@@ -119,4 +121,10 @@ impl CompositorEventListener for NullCompositor {
self.time_profiler_chan.send(time::ExitMsg);
self.memory_profiler_chan.send(memory::ExitMsg);
}
+
+ fn pinch_zoom_level(&self) -> f32 {
+ 1.0
+ }
+
+ fn get_title_for_main_frame(&self) {}
}
diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs
index cf1ebd16f8c..6dd9dabb0bf 100644
--- a/components/compositing/pipeline.rs
+++ b/components/compositing/pipeline.rs
@@ -28,8 +28,10 @@ pub struct Pipeline {
pub paint_chan: PaintChan,
pub layout_shutdown_port: Receiver<()>,
pub paint_shutdown_port: Receiver<()>,
- /// The most recently loaded page
+ /// Load data corresponding to the most recently-loaded page.
pub load_data: LoadData,
+ /// The title of the most recently-loaded page.
+ pub title: Option<String>,
}
/// The subset of the pipeline that is needed for layer composition.
@@ -44,21 +46,21 @@ impl Pipeline {
/// Starts a paint task, layout task, and possibly a script task.
/// Returns the channels wrapped in a struct.
/// If script_pipeline is not None, then subpage_id must also be not None.
- pub fn create<LTF:LayoutTaskFactory, STF:ScriptTaskFactory>(
- id: PipelineId,
- subpage_id: Option<SubpageId>,
- constellation_chan: ConstellationChan,
- compositor_proxy: Box<CompositorProxy+'static+Send>,
- devtools_chan: Option<DevtoolsControlChan>,
- image_cache_task: ImageCacheTask,
- font_cache_task: FontCacheTask,
- resource_task: ResourceTask,
- storage_task: StorageTask,
- time_profiler_chan: TimeProfilerChan,
- window_size: WindowSizeData,
- script_pipeline: Option<Rc<Pipeline>>,
- load_data: LoadData)
- -> Pipeline {
+ pub fn create<LTF,STF>(id: PipelineId,
+ subpage_id: Option<SubpageId>,
+ constellation_chan: ConstellationChan,
+ compositor_proxy: Box<CompositorProxy+'static+Send>,
+ devtools_chan: Option<DevtoolsControlChan>,
+ image_cache_task: ImageCacheTask,
+ font_cache_task: FontCacheTask,
+ resource_task: ResourceTask,
+ storage_task: StorageTask,
+ time_profiler_chan: TimeProfilerChan,
+ window_size: WindowSizeData,
+ script_pipeline: Option<Rc<Pipeline>>,
+ load_data: LoadData)
+ -> Pipeline
+ where LTF: LayoutTaskFactory, STF:ScriptTaskFactory {
let layout_pair = ScriptTaskFactory::create_layout_channel(None::<&mut STF>);
let (paint_port, paint_chan) = PaintChan::new();
let (paint_shutdown_chan, paint_shutdown_port) = channel();
@@ -153,6 +155,7 @@ impl Pipeline {
layout_shutdown_port: layout_shutdown_port,
paint_shutdown_port: paint_shutdown_port,
load_data: load_data,
+ title: None,
}
}
diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs
index 0dffe0a8f94..339a5fe789d 100644
--- a/components/compositing/windowing.rs
+++ b/components/compositing/windowing.rs
@@ -11,8 +11,8 @@ use geom::scale_factor::ScaleFactor;
use geom::size::TypedSize2D;
use layers::geometry::DevicePixel;
use layers::platform::surface::NativeGraphicsMetadata;
-use servo_msg::constellation_msg::{Key, KeyState, KeyModifiers};
-use servo_msg::compositor_msg::{ReadyState, PaintState};
+use servo_msg::compositor_msg::{PaintState, ReadyState};
+use servo_msg::constellation_msg::{Key, KeyState, KeyModifiers, LoadData};
use servo_util::geometry::ScreenPx;
use std::fmt::{FormatError, Formatter, Show};
use std::rc::Rc;
@@ -37,8 +37,12 @@ pub enum WindowEvent {
/// It's possible that this should be something like
/// `CompositorMessageWindowEvent(compositor_task::Msg)` instead.
IdleWindowEvent,
- /// Sent when part of the window is marked dirty and needs to be redrawn.
+ /// Sent when part of the window is marked dirty and needs to be redrawn. Before sending this
+ /// message, the window must make the same GL context as in `PrepareRenderingEvent` current.
RefreshWindowEvent,
+ /// Sent to initialize the GL context. The windowing system must have a valid, current GL
+ /// context when this message is sent.
+ InitializeCompositingWindowEvent,
/// Sent when the window is resized.
ResizeWindowEvent(TypedSize2D<DevicePixel, uint>),
/// Sent when a new URL is to be loaded.
@@ -47,7 +51,8 @@ pub enum WindowEvent {
MouseWindowEventClass(MouseWindowEvent),
/// Sent when a mouse move.
MouseWindowMoveEventClass(TypedPoint2D<DevicePixel, f32>),
- /// Sent when the user scrolls. Includes the current cursor position.
+ /// Sent when the user scrolls. The first point is the delta and the second point is the
+ /// origin.
ScrollWindowEvent(TypedPoint2D<DevicePixel, f32>, TypedPoint2D<DevicePixel, i32>),
/// Sent when the user zooms.
ZoomWindowEvent(f32),
@@ -66,6 +71,7 @@ impl Show for WindowEvent {
match *self {
IdleWindowEvent => write!(f, "Idle"),
RefreshWindowEvent => write!(f, "Refresh"),
+ InitializeCompositingWindowEvent => write!(f, "InitializeCompositing"),
ResizeWindowEvent(..) => write!(f, "Resize"),
KeyEvent(..) => write!(f, "Key"),
LoadUrlWindowEvent(..) => write!(f, "LoadUrl"),
@@ -92,6 +98,12 @@ pub trait WindowMethods {
fn set_ready_state(&self, ready_state: ReadyState);
/// Sets the paint state of the current page.
fn set_paint_state(&self, paint_state: PaintState);
+ /// Sets the page title for the current page.
+ fn set_page_title(&self, title: Option<String>);
+ /// Sets the load data for the current page.
+ fn set_page_load_data(&self, load_data: LoadData);
+ /// Called when the browser is done loading a frame.
+ fn load_end(&self);
/// Returns the hidpi factor of the monitor.
fn hidpi_factor(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32>;
@@ -106,5 +118,10 @@ pub trait WindowMethods {
/// magic to wake the up window's event loop.
fn create_compositor_channel(_: &Option<Rc<Self>>)
-> (Box<CompositorProxy+Send>, Box<CompositorReceiver>);
+
+ /// Requests that the window system prepare a composite. Typically this will involve making
+ /// some type of platform-specific graphics context current. Returns true if the composite may
+ /// proceed and false if it should not.
+ fn prepare_for_composite(&self) -> bool;
}
diff --git a/components/msg/compositor_msg.rs b/components/msg/compositor_msg.rs
index 4635e2667d4..dad31c08976 100644
--- a/components/msg/compositor_msg.rs
+++ b/components/msg/compositor_msg.rs
@@ -19,7 +19,7 @@ pub enum PaintState {
PaintingPaintState,
}
-#[deriving(Eq, Ord, PartialEq, PartialOrd, Clone)]
+#[deriving(Eq, Ord, PartialEq, PartialOrd, Clone, Show)]
pub enum ReadyState {
/// Informs the compositor that nothing has been done yet. Used for setting status
Blank,
@@ -111,6 +111,8 @@ pub trait ScriptListener {
pipeline_id: PipelineId,
layer_id: LayerId,
point: Point2D<f32>);
+ /// Informs the compositor that the title of the page with the given pipeline ID has changed.
+ fn set_title(&mut self, pipeline_id: PipelineId, new_title: Option<String>);
fn close(&mut self);
fn dup(&mut self) -> Box<ScriptListener+'static>;
}
diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs
index 483f03803cf..9b2a654310c 100644
--- a/components/msg/constellation_msg.rs
+++ b/components/msg/constellation_msg.rs
@@ -205,6 +205,9 @@ pub enum Msg {
PainterReadyMsg(PipelineId),
ResizedWindowMsg(WindowSizeData),
KeyEvent(Key, KeyState, KeyModifiers),
+ /// Requests that the constellation inform the compositor of the title of the pipeline
+ /// immediately.
+ GetPipelineTitleMsg(PipelineId),
}
/// Similar to net::resource_task::LoadData
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 4fbdaab837d..738ac6be90e 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -189,6 +189,7 @@ pub trait DocumentHelpers<'a> {
fn begin_focus_transaction(self);
fn request_focus(self, elem: JSRef<Element>);
fn commit_focus_transaction(self);
+ fn send_title_to_compositor(self);
}
impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
@@ -369,6 +370,12 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
//TODO: dispatch blur, focus, focusout, and focusin events
self.focused.assign(self.possibly_focused.get());
}
+
+ /// Sends this document's title to the compositor.
+ fn send_title_to_compositor(self) {
+ let window = self.window().root();
+ window.page().send_title_to_compositor();
+ }
}
#[deriving(PartialEq)]
@@ -985,3 +992,4 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
global_event_handlers!()
event_handler!(readystatechange, GetOnreadystatechange, SetOnreadystatechange)
}
+
diff --git a/components/script/dom/htmltitleelement.rs b/components/script/dom/htmltitleelement.rs
index ef8b70aa4fa..4e6e9f7e9bb 100644
--- a/components/script/dom/htmltitleelement.rs
+++ b/components/script/dom/htmltitleelement.rs
@@ -5,15 +5,17 @@
use dom::bindings::codegen::Bindings::HTMLTitleElementBinding;
use dom::bindings::codegen::Bindings::HTMLTitleElementBinding::HTMLTitleElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
-use dom::bindings::codegen::InheritTypes::{HTMLTitleElementDerived, NodeCast, TextCast};
+use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLTitleElementDerived, NodeCast};
+use dom::bindings::codegen::InheritTypes::{TextCast};
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector};
-use dom::document::Document;
+use dom::document::{Document, DocumentHelpers};
use dom::element::HTMLTitleElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, NodeHelpers, ElementNodeTypeId};
use dom::text::Text;
+use dom::virtualmethods::VirtualMethods;
use servo_util::str::DOMString;
#[dom_struct]
@@ -68,3 +70,19 @@ impl Reflectable for HTMLTitleElement {
self.htmlelement.reflector()
}
}
+
+impl<'a> VirtualMethods for JSRef<'a, HTMLTitleElement> {
+ fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
+ let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
+ Some(htmlelement as &VirtualMethods)
+ }
+
+ fn bind_to_tree(&self, is_in_doc: bool) {
+ let node: JSRef<Node> = NodeCast::from_ref(*self);
+ if is_in_doc {
+ let document = node.owner_doc().root();
+ document.send_title_to_compositor()
+ }
+ }
+}
+
diff --git a/components/script/dom/virtualmethods.rs b/components/script/dom/virtualmethods.rs
index 66378463a82..a90055bc50d 100644
--- a/components/script/dom/virtualmethods.rs
+++ b/components/script/dom/virtualmethods.rs
@@ -24,6 +24,7 @@ use dom::bindings::codegen::InheritTypes::HTMLSelectElementCast;
use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast;
use dom::bindings::codegen::InheritTypes::HTMLTableCellElementCast;
use dom::bindings::codegen::InheritTypes::HTMLTextAreaElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLTitleElementCast;
use dom::bindings::js::JSRef;
use dom::document::Document;
use dom::element::Element;
@@ -47,6 +48,7 @@ use dom::element::HTMLStyleElementTypeId;
use dom::element::HTMLTableDataCellElementTypeId;
use dom::element::HTMLTableHeaderCellElementTypeId;
use dom::element::HTMLTextAreaElementTypeId;
+use dom::element::HTMLTitleElementTypeId;
use dom::event::Event;
use dom::htmlanchorelement::HTMLAnchorElement;
use dom::htmlareaelement::HTMLAreaElement;
@@ -67,6 +69,7 @@ use dom::htmlselectelement::HTMLSelectElement;
use dom::htmlstyleelement::HTMLStyleElement;
use dom::htmltablecellelement::HTMLTableCellElement;
use dom::htmltextareaelement::HTMLTextAreaElement;
+use dom::htmltitleelement::HTMLTitleElement;
use dom::node::{Node, NodeHelpers, ElementNodeTypeId, CloneChildrenFlag};
use servo_util::str::DOMString;
@@ -232,6 +235,11 @@ pub fn vtable_for<'a>(node: &'a JSRef<'a, Node>) -> &'a VirtualMethods + 'a {
let element: &'a JSRef<'a, HTMLTextAreaElement> = HTMLTextAreaElementCast::to_borrowed_ref(node).unwrap();
element as &'a VirtualMethods + 'a
}
+ ElementNodeTypeId(HTMLTitleElementTypeId) => {
+ let element: &'a JSRef<'a, HTMLTitleElement> =
+ HTMLTitleElementCast::to_borrowed_ref(node).unwrap();
+ element as &'a VirtualMethods + 'a
+ }
ElementNodeTypeId(ElementTypeId_) => {
let element: &'a JSRef<'a, Element> = ElementCast::to_borrowed_ref(node).unwrap();
element as &'a VirtualMethods + 'a
diff --git a/components/script/page.rs b/components/script/page.rs
index 37f4ba155bb..c8e46463077 100644
--- a/components/script/page.rs
+++ b/components/script/page.rs
@@ -21,7 +21,6 @@ use script_traits::{UntrustedNodeAddress, ScriptControlChan};
use geom::{Point2D, Rect, Size2D};
use js::rust::Cx;
-use servo_msg::compositor_msg::PerformingLayout;
use servo_msg::compositor_msg::ScriptListener;
use servo_msg::constellation_msg::{ConstellationChan, WindowSizeData};
use servo_msg::constellation_msg::{PipelineId, SubpageId};
@@ -266,6 +265,17 @@ impl Page {
// because it was built for infinite clip (MAX_RECT).
had_clip_rect
}
+
+ pub fn send_title_to_compositor(&self) {
+ match *self.frame() {
+ None => {}
+ Some(ref frame) => {
+ let window = frame.window.root();
+ let document = frame.document.root();
+ window.compositor().set_title(self.id, Some(document.Title()));
+ }
+ }
+ }
}
impl Iterator<Rc<Page>> for PageIterator {
@@ -356,7 +366,7 @@ impl Page {
pub fn reflow(&self,
goal: ReflowGoal,
script_chan: ScriptControlChan,
- compositor: &mut ScriptListener,
+ _: &mut ScriptListener,
query_type: ReflowQueryType) {
let root = match *self.frame() {
None => return,
@@ -376,9 +386,6 @@ impl Page {
// Now, join the layout so that they will see the latest changes we have made.
self.join_layout();
- // Tell the user that we're performing layout.
- compositor.set_ready_state(self.id, PerformingLayout);
-
// Layout will let us know when it's done.
let (join_chan, join_port) = channel();
let mut layout_join_port = self.layout_join_port.borrow_mut();
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index f41558b598c..b4fdaa6f833 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -43,10 +43,12 @@ use script_traits::{MouseMoveEvent, MouseUpEvent, ConstellationControlMsg, Scrip
use script_traits::{ResizeMsg, AttachLayoutMsg, LoadMsg, ViewportMsg, SendEventMsg};
use script_traits::{ResizeInactiveMsg, ExitPipelineMsg, NewLayoutInfo, OpaqueScriptLayoutChannel};
use script_traits::{ScriptControlChan, ReflowCompleteMsg, UntrustedNodeAddress, KeyEvent};
-use servo_msg::compositor_msg::{FinishedLoading, LayerId, Loading};
+use script_traits::{GetTitleMsg};
+use servo_msg::compositor_msg::{FinishedLoading, LayerId, Loading, PerformingLayout};
use servo_msg::compositor_msg::{ScriptListener};
-use servo_msg::constellation_msg::{ConstellationChan, LoadCompleteMsg, LoadUrlMsg, NavigationDirection};
-use servo_msg::constellation_msg::{LoadData, PipelineId, Failure, FailureMsg, WindowSizeData, Key, KeyState};
+use servo_msg::constellation_msg::{ConstellationChan, LoadCompleteMsg};
+use servo_msg::constellation_msg::{LoadData, LoadUrlMsg, NavigationDirection, PipelineId};
+use servo_msg::constellation_msg::{Failure, FailureMsg, WindowSizeData, Key, KeyState};
use servo_msg::constellation_msg::{KeyModifiers, SUPER, SHIFT, CONTROL, ALT, Repeated, Pressed};
use servo_msg::constellation_msg::{Released};
use servo_msg::constellation_msg;
@@ -550,6 +552,9 @@ impl ScriptTask {
FromConstellation(ViewportMsg(..)) => panic!("should have handled ViewportMsg already"),
FromScript(ExitWindowMsg(id)) => self.handle_exit_window_msg(id),
FromConstellation(ResizeMsg(..)) => panic!("should have handled ResizeMsg already"),
+ FromConstellation(GetTitleMsg(pipeline_id)) => {
+ self.handle_get_title_msg(pipeline_id)
+ }
FromScript(XHRProgressMsg(addr, progress)) => XMLHttpRequest::handle_progress(addr, progress),
FromScript(XHRReleaseMsg(addr)) => XMLHttpRequest::handle_release(addr),
FromScript(DOMMessage(..)) => panic!("unexpected message"),
@@ -661,6 +666,11 @@ impl ScriptTask {
self.compositor.borrow_mut().close();
}
+ /// Handles a request for the window title.
+ fn handle_get_title_msg(&self, pipeline_id: PipelineId) {
+ get_page(&*self.page.borrow(), pipeline_id).send_title_to_compositor();
+ }
+
/// 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(&self, id: PipelineId) -> bool {
@@ -784,6 +794,7 @@ impl ScriptTask {
parse_html(*document, parser_input, &final_url);
document.set_ready_state(DocumentReadyStateValues::Interactive);
+ self.compositor.borrow_mut().set_ready_state(pipeline_id, PerformingLayout);
// Kick off the initial reflow of the page.
debug!("kicking off initial reflow of {}", final_url);
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index dec1d090178..59a1447a75a 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -65,7 +65,10 @@ pub enum ConstellationControlMsg {
SendEventMsg(PipelineId, CompositorEvent),
/// Notifies script that reflow is finished.
ReflowCompleteMsg(PipelineId, uint),
+ /// Notifies script of the viewport.
ViewportMsg(PipelineId, Rect<f32>),
+ /// Requests that the script task immediately send the constellation the title of a pipeline.
+ GetTitleMsg(PipelineId),
}
/// Events from the compositor that the script task needs to know about
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index ade8b873593..f9200ea627c 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -58,7 +58,7 @@ dependencies = [
[[package]]
name = "cocoa"
version = "0.1.1"
-source = "git+https://github.com/servo/rust-cocoa#78b823bec1affcab20b6977e1057125088a6034c"
+source = "git+https://github.com/servo/rust-cocoa#084f8e1baf40391eb12819d16765af25ca96c7ec"
[[package]]
name = "compile_msg"
@@ -394,7 +394,7 @@ source = "git+https://github.com/bjz/gl-rs.git#79cd3b3f9f19aa0e39f6af572fc8673a6
[[package]]
name = "layers"
version = "0.1.0"
-source = "git+https://github.com/servo/rust-layers#b068d2a96d54bf173b548aece36f5ea4ef9353cf"
+source = "git+https://github.com/servo/rust-layers#63d1093f2a01a6fb9599ea6d932aadf79598451f"
dependencies = [
"cgl 0.0.1 (git+https://github.com/servo/rust-cgl)",
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index 1ddfbc1dc5d..9e5d4be9467 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -153,6 +153,14 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static {
self.compositor.repaint_synchronously()
}
+ pub fn pinch_zoom_level(&self) -> f32 {
+ self.compositor.pinch_zoom_level()
+ }
+
+ pub fn get_title_for_main_frame(&self) {
+ self.compositor.get_title_for_main_frame()
+ }
+
pub fn shutdown(mut self) {
self.compositor.shutdown();
}
diff --git a/components/servo/main.rs b/components/servo/main.rs
index 16ef1980668..a6d7f28db73 100644
--- a/components/servo/main.rs
+++ b/components/servo/main.rs
@@ -30,7 +30,9 @@ use servo_util::rtinstrument;
#[cfg(not(any(test,target_os="android")))]
use servo::Browser;
#[cfg(not(any(test,target_os="android")))]
-use compositing::windowing::{IdleWindowEvent, ResizeWindowEvent, WindowEvent};
+use compositing::windowing::{IdleWindowEvent, InitializeCompositingWindowEvent, ResizeWindowEvent};
+#[cfg(not(any(test,target_os="android")))]
+use compositing::windowing::{WindowEvent};
#[cfg(not(any(test,target_os="android")))]
use std::os;
@@ -65,6 +67,8 @@ fn start(argc: int, argv: *const *const u8) -> int {
}
}
+ browser.browser.handle_event(InitializeCompositingWindowEvent);
+
loop {
let should_continue = match window {
None => browser.browser.handle_event(IdleWindowEvent),