auto merge of #1712 : larsbergstrom/servo/more_atmuts, r=larsbergstrom,metajack

These commits remove @mut from the rest of Servo except for the script crate.

They rely on the hack `Rc` type exported from rust-layers, which will be removed once that same version lands in our Rust upgrade, but is required for now because otherwise I'd have to make all of these structures either `Send` or `Freeze`.

r? @metajack or @kmcallister
This commit is contained in:
bors-servo 2014-02-21 19:46:54 -05:00
commit 006237fed3
8 changed files with 425 additions and 327 deletions

View file

@ -39,12 +39,16 @@ use servo_util::{time, url};
use std::comm::Port;
use std::num::Orderable;
use std::path::Path;
use std::rc::Rc;
//FIXME: switch to std::rc when we upgrade Rust
use layers::temp_rc::Rc;
//use std::rc::Rc;
use std::rc;
pub struct IOCompositor {
/// The application window.
window: Rc<Window>,
window: rc::Rc<Window>,
/// The port on which we receive messages.
port: Port<Msg>,
@ -53,7 +57,7 @@ pub struct IOCompositor {
context: RenderContext,
/// The root ContainerLayer.
root_layer: @mut ContainerLayer,
root_layer: Rc<ContainerLayer>,
/// The canvas to paint a page.
scene: Scene,
@ -116,13 +120,13 @@ impl IOCompositor {
port: Port<Msg>,
constellation_chan: ConstellationChan,
profiler_chan: ProfilerChan) -> IOCompositor {
let window: Rc<Window> = WindowMethods::new(app);
let window: rc::Rc<Window> = WindowMethods::new(app);
// Create an initial layer tree.
//
// TODO: There should be no initial layer tree until the renderer creates one from the display
// list. This is only here because we don't have that logic in the renderer yet.
let root_layer = @mut ContainerLayer();
let root_layer = Rc::new(ContainerLayer());
let window_size = window.borrow().size();
IOCompositor {
@ -130,7 +134,7 @@ impl IOCompositor {
port: port,
opts: opts,
context: rendergl::init_render_context(),
root_layer: root_layer,
root_layer: root_layer.clone(),
scene: Scene(ContainerLayerKind(root_layer), window_size, identity()),
window_size: Size2D(window_size.width as uint, window_size.height as uint),
graphics_context: CompositorTask::create_graphics_context(),
@ -317,16 +321,22 @@ impl IOCompositor {
response_chan.send(());
// This assumes there is at most one child, which should be the case.
match self.root_layer.first_child {
Some(old_layer) => self.root_layer.remove_child(old_layer),
None => {}
// NOTE: work around borrowchk
{
let tmp = self.root_layer.borrow().first_child.borrow();
match *tmp.get() {
Some(ref old_layer) => ContainerLayer::remove_child(self.root_layer.clone(),
old_layer.clone()),
None => {}
}
}
let layer = CompositorLayer::from_frame_tree(frame_tree,
self.opts.tile_size,
Some(10000000u),
self.opts.cpu_painting);
self.root_layer.add_child_start(ContainerLayerKind(layer.root_layer));
ContainerLayer::add_child_start(self.root_layer.clone(),
ContainerLayerKind(layer.root_layer.clone()));
// If there's already a root layer, destroy it cleanly.
match self.compositor_layer {
@ -360,13 +370,17 @@ impl IOCompositor {
Some(10000000u),
self.opts.cpu_painting);
let current_child = self.root_layer.first_child;
// This assumes there is at most one child, which should be the case.
match current_child {
Some(old_layer) => self.root_layer.remove_child(old_layer),
None => {}
{
let current_child = self.root_layer.borrow().first_child.borrow();
// This assumes there is at most one child, which should be the case.
match *current_child.get() {
Some(ref old_layer) => ContainerLayer::remove_child(self.root_layer.clone(),
old_layer.clone()),
None => {}
}
}
self.root_layer.add_child_start(ContainerLayerKind(new_layer.root_layer));
ContainerLayer::add_child_start(self.root_layer.clone(),
ContainerLayerKind(new_layer.root_layer.clone()));
self.compositor_layer = Some(new_layer);
self.ask_for_tiles();
@ -617,7 +631,7 @@ impl IOCompositor {
self.world_zoom = (self.world_zoom * magnification).max(&1.0);
let world_zoom = self.world_zoom;
self.root_layer.common.set_transform(identity().scale(world_zoom, world_zoom, 1f32));
self.root_layer.borrow().common.with_mut(|common| common.set_transform(identity().scale(world_zoom, world_zoom, 1f32)));
// Scroll as needed
let page_delta = Point2D(window_size.width as f32 * (1.0 / world_zoom - 1.0 / old_world_zoom) * 0.5,

View file

@ -22,6 +22,9 @@ use script::dom::event::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEven
use script::script_task::SendEventMsg;
use servo_msg::compositor_msg::{LayerBuffer, LayerBufferSet, Epoch, Tile};
use servo_msg::constellation_msg::PipelineId;
//FIXME: switch to std::rc when we upgrade Rust
use layers::temp_rc::Rc;
//use std::rc::Rc;
use windowing::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent};
use windowing::{MouseWindowMouseUpEvent};
use azure::azure_hl::Color;
@ -57,7 +60,7 @@ pub struct CompositorLayer {
/// The root layer of this CompositorLayer's layer tree. Buffers are collected
/// from the quadtree and inserted here when the layer is painted to the screen.
root_layer: @mut ContainerLayer,
root_layer: Rc<ContainerLayer>,
/// When set to true, this layer is ignored by its parents. This is useful for
/// soft deletion or when waiting on a page size.
@ -83,7 +86,7 @@ struct CompositorLayerChild {
child: ~CompositorLayer,
/// A ContainerLayer managed by the parent node. This deals with clipping and
/// positioning, and is added above the child's layer tree.
container: @mut ContainerLayer,
container: Rc<ContainerLayer>,
}
/// Helper enum for storing quadtrees. Either contains a quadtree, or contains
@ -123,7 +126,7 @@ impl CompositorLayer {
tile_size,
max_mem)),
},
root_layer: @mut ContainerLayer(),
root_layer: Rc::new(ContainerLayer()),
hidden: true,
epoch: Epoch(0),
scroll_behavior: Scroll,
@ -142,14 +145,13 @@ impl CompositorLayer {
let mut layer = CompositorLayer::new(pipeline, None, tile_size, max_mem, cpu_painting);
layer.children = (children.move_iter().map(|child| {
let SendableChildFrameTree { frame_tree, rect } = child;
let container = @mut ContainerLayer();
let container = Rc::new(ContainerLayer());
match rect {
Some(rect) => {
container.scissor = Some(rect);
container.common.transform = identity().translate(rect.origin.x,
rect.origin.y,
0f32);
container.borrow().scissor.set(Some(rect));
container.borrow().common.with_mut(|common| common.transform = identity().translate(rect.origin.x,
rect.origin.y,
0f32));
}
None => {}
}
@ -158,7 +160,7 @@ impl CompositorLayer {
tile_size,
max_mem,
cpu_painting);
container.add_child_start(ContainerLayerKind(child_layer.root_layer));
ContainerLayer::add_child_start(container.clone(), ContainerLayerKind(child_layer.root_layer.clone()));
CompositorLayerChild {
child: child_layer,
@ -177,7 +179,9 @@ impl CompositorLayer {
-> bool {
let cursor = cursor - self.scroll_offset;
for child in self.children.mut_iter().filter(|x| !x.child.hidden) {
match child.container.scissor {
// NOTE: work around borrowchk
let tmp = child.container.borrow().scissor.borrow();
match *tmp.get() {
None => {
error!("CompositorLayer: unable to perform cursor hit test for layer");
}
@ -213,9 +217,9 @@ impl CompositorLayer {
return false;
}
self.root_layer.common.set_transform(identity().translate(self.scroll_offset.x,
self.scroll_offset.y,
0.0));
self.root_layer.borrow().common.with_mut(|common| common.set_transform(identity().translate(self.scroll_offset.x,
self.scroll_offset.y,
0.0)));
true
}
FixedPosition => false, // Ignore this scroll event.
@ -228,7 +232,9 @@ impl CompositorLayer {
pub fn send_mouse_event(&self, event: MouseWindowEvent, cursor: Point2D<f32>) {
let cursor = cursor - self.scroll_offset;
for child in self.children.iter().filter(|&x| !x.child.hidden) {
match child.container.scissor {
// NOTE: work around borrowchk
let tmp = child.container.borrow().scissor.borrow();
match *tmp.get() {
None => {
error!("CompositorLayer: unable to perform cursor hit test for layer");
}
@ -287,7 +293,9 @@ impl CompositorLayer {
self.build_layer_tree(graphics_context);
}
let transform = |x: &mut CompositorLayerChild| -> bool {
match x.container.scissor {
// NOTE: work around borrowchk
let tmp = x.container.borrow().scissor.borrow();
match *tmp.get() {
Some(scissor) => {
let new_rect = rect.intersection(&scissor);
match new_rect {
@ -323,12 +331,16 @@ impl CompositorLayer {
match self.children.iter().position(|x| pipeline_id == x.child.pipeline.id) {
Some(i) => {
let child_node = &mut self.children[i];
let con = child_node.container;
con.common.set_transform(identity().translate(new_rect.origin.x,
new_rect.origin.y,
0.0));
let old_rect = con.scissor;
con.scissor = Some(new_rect);
child_node.container.borrow().common.with_mut(|common|
common.set_transform(identity().translate(new_rect.origin.x,
new_rect.origin.y,
0.0)));
let old_rect = {
// NOTE: work around borrowchk
let tmp = child_node.container.borrow().scissor.borrow();
tmp.get().clone()
};
child_node.container.borrow().scissor.set(Some(new_rect));
match self.quadtree {
NoTree(..) => {} // Nothing to do
Tree(ref mut quadtree) => {
@ -408,9 +420,10 @@ impl CompositorLayer {
return false;
}
self.root_layer.common.set_transform(identity().translate(self.scroll_offset.x,
self.scroll_offset.y,
0.0));
self.root_layer.borrow().common.with_mut(|common|
common.set_transform(identity().translate(self.scroll_offset.x,
self.scroll_offset.y,
0.0)));
true
}
FixedPosition => false // Ignore this scroll event.
@ -465,7 +478,9 @@ impl CompositorLayer {
max_mem))
}
}
match child_node.container.scissor {
// NOTE: work around borrowchk
let tmp = child_node.container.borrow().scissor.borrow();
match *tmp.get() {
Some(scissor) => {
// Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the cursor position
// to make sure the scroll isn't propagated downwards.
@ -492,15 +507,21 @@ impl CompositorLayer {
// are not rebuilt directly from this method.
pub fn build_layer_tree(&mut self, graphics_context: &NativeCompositingGraphicsContext) {
// Iterate over the children of the container layer.
let mut current_layer_child = self.root_layer.first_child;
let mut current_layer_child;
// NOTE: work around borrowchk
{
let tmp = self.root_layer.borrow().first_child.borrow();
current_layer_child = tmp.get().clone();
}
// Delete old layer.
while current_layer_child.is_some() {
let trash = current_layer_child.unwrap();
current_layer_child.unwrap().with_common(|common| {
current_layer_child = common.next_sibling;
let trash = current_layer_child.clone().unwrap();
current_layer_child.clone().unwrap().with_common(|common| {
current_layer_child = common.next_sibling.clone();
});
self.root_layer.remove_child(trash);
ContainerLayer::remove_child(self.root_layer.clone(), trash);
}
// Add new tiles.
@ -519,7 +540,7 @@ impl CompositorLayer {
// Find or create a texture layer.
let texture_layer;
current_layer_child = match current_layer_child {
current_layer_child = match current_layer_child.clone() {
None => {
debug!("osmain: adding new texture layer");
@ -536,19 +557,20 @@ impl CompositorLayer {
buffer.native_surface.bind_to_texture(graphics_context, &texture, size);
// Make a texture layer and add it.
texture_layer = @mut TextureLayer::new(texture, buffer.screen_pos.size, flip);
self.root_layer.add_child_end(TextureLayerKind(texture_layer));
texture_layer = Rc::new(TextureLayer::new(texture, buffer.screen_pos.size, flip));
ContainerLayer::add_child_end(self.root_layer.clone(),
TextureLayerKind(texture_layer.clone()));
None
}
Some(TextureLayerKind(existing_texture_layer)) => {
texture_layer = existing_texture_layer;
texture_layer = existing_texture_layer.clone();
let texture = &texture_layer.texture;
let texture = &existing_texture_layer.borrow().texture;
buffer.native_surface.bind_to_texture(graphics_context, texture, size);
// Move on to the next sibling.
current_layer_child.unwrap().with_common(|common| {
common.next_sibling
common.next_sibling.clone()
})
}
Some(_) => fail!(~"found unexpected layer kind"),
@ -558,17 +580,20 @@ impl CompositorLayer {
let rect = buffer.rect;
let transform = identity().translate(rect.origin.x, rect.origin.y, 0.0);
let transform = transform.scale(rect.size.width, rect.size.height, 1.0);
texture_layer.common.set_transform(transform);
texture_layer.borrow().common.with_mut(|common| common.set_transform(transform));
}
// Add child layers.
for child in self.children.mut_iter().filter(|x| !x.child.hidden) {
current_layer_child = match current_layer_child {
None => {
child.container.common.parent = None;
child.container.common.prev_sibling = None;
child.container.common.next_sibling = None;
self.root_layer.add_child_end(ContainerLayerKind(child.container));
child.container.borrow().common.with_mut(|common| {
common.parent = None;
common.prev_sibling = None;
common.next_sibling = None;
});
ContainerLayer::add_child_end(self.root_layer.clone(),
ContainerLayerKind(child.container.clone()));
None
}
Some(_) => {
@ -648,7 +673,9 @@ impl CompositorLayer {
match self.quadtree {
NoTree(..) => {} // Nothing to do
Tree(ref mut quadtree) => {
match child.container.scissor {
// NOTE: work around borrowchk
let tmp = child.container.borrow().scissor.borrow();
match *tmp.get() {
Some(rect) => {
quadtree.set_status_page(rect, Normal, false); // Unhide this rect
}
@ -692,7 +719,9 @@ impl CompositorLayer {
Tree(ref mut quadtree) => quadtree,
};
for child in self.children.iter().filter(|x| !x.child.hidden) {
match child.container.scissor {
// NOTE: work around borrowchk
let tmp = child.container.borrow().scissor.borrow();
match *tmp.get() {
None => {} // Nothing to do
Some(rect) => {
quadtree.set_status_page(rect, Hidden, false);

View file

@ -24,7 +24,11 @@ use servo_net::resource_task;
use servo_util::time::ProfilerChan;
use servo_util::url::parse_url;
use servo_util::task::spawn_named;
use std::cell::RefCell;
use std::hashmap::{HashMap, HashSet};
//FIXME: switch to std::rc when we upgrade Rust
use layers::temp_rc::Rc;
//use std::rc::Rc;
use std::util::replace;
use std::io;
use std::libc;
@ -36,7 +40,7 @@ pub struct Constellation {
compositor_chan: CompositorChan,
resource_task: ResourceTask,
image_cache_task: ImageCacheTask,
pipelines: HashMap<PipelineId, @mut Pipeline>,
pipelines: HashMap<PipelineId, Rc<Pipeline>>,
navigation_context: NavigationContext,
priv next_pipeline_id: PipelineId,
pending_frames: ~[FrameChange],
@ -48,27 +52,28 @@ pub struct Constellation {
/// Stores the Id of the outermost frame's pipeline, along with a vector of children frames
struct FrameTree {
pipeline: @mut Pipeline,
parent: Option<@mut Pipeline>,
children: ~[ChildFrameTree],
pipeline: RefCell<Rc<Pipeline>>,
parent: RefCell<Option<Rc<Pipeline>>>,
children: RefCell<~[ChildFrameTree]>,
}
// Need to clone the FrameTrees, but _not_ the Pipelines
impl Clone for FrameTree {
fn clone(&self) -> FrameTree {
let mut children = self.children.iter().map(|child_frame_tree| {
let children = self.children.borrow();
let mut children = children.get().iter().map(|child_frame_tree| {
child_frame_tree.clone()
});
FrameTree {
pipeline: self.pipeline,
pipeline: self.pipeline.clone(),
parent: self.parent.clone(),
children: children.collect(),
children: RefCell::new(children.collect()),
}
}
}
struct ChildFrameTree {
frame_tree: @mut FrameTree,
frame_tree: Rc<FrameTree>,
/// Clipping rect representing the size and position, in page coordinates, of the visible
/// region of the child frame relative to the parent.
rect: Option<Rect<f32>>,
@ -77,7 +82,7 @@ struct ChildFrameTree {
impl Clone for ChildFrameTree {
fn clone(&self) -> ChildFrameTree {
ChildFrameTree {
frame_tree: @mut (*self.frame_tree).clone(),
frame_tree: self.frame_tree.clone(),
rect: self.rect.clone(),
}
}
@ -103,32 +108,46 @@ pub struct SendableChildFrameTree {
// }
enum ReplaceResult {
ReplacedNode(@mut FrameTree),
OriginalNode(@mut FrameTree),
ReplacedNode(Rc<FrameTree>),
OriginalNode(Rc<FrameTree>),
}
impl FrameTree {
fn contains(@mut self, id: PipelineId) -> bool {
fn contains(&self, id: PipelineId) -> bool {
self.iter().any(|frame_tree| {
id == frame_tree.pipeline.id
// NOTE: work around borrowchk issue
let tmp = frame_tree.borrow().pipeline.borrow();
id == tmp.get().borrow().id
})
}
/// Returns the frame tree whose key is id
fn find(@mut self, id: PipelineId) -> Option<@mut FrameTree> {
fn find(&self, id: PipelineId) -> Option<Rc<FrameTree>> {
self.iter().find(|frame_tree| {
id == frame_tree.pipeline.id
// NOTE: work around borrowchk issue
let tmp = frame_tree.borrow().pipeline.borrow();
id == tmp.get().borrow().id
})
}
/// Replaces a node of the frame tree in place. Returns the node that was removed or the original node
/// if the node to replace could not be found.
fn replace_child(@mut self, id: PipelineId, new_child: @mut FrameTree) -> ReplaceResult {
fn replace_child(&self, id: PipelineId, new_child: Rc<FrameTree>) -> ReplaceResult {
for frame_tree in self.iter() {
let mut child = frame_tree.children.mut_iter()
.find(|child| child.frame_tree.pipeline.id == id);
// NOTE: work around mutability issue
let mut children = frame_tree.borrow().children.borrow_mut();
let mut child = children.get().mut_iter()
.find(|child| {
// NOTE: work around borrowchk issue
let tmp = child.frame_tree.borrow().pipeline.borrow();
tmp.get().borrow().id == id
});
for child in child.mut_iter() {
new_child.parent = child.frame_tree.parent;
// NOTE: work around lifetime issues
{
let tmp = child.frame_tree.borrow().parent.borrow();
new_child.borrow().parent.set(tmp.get().clone());
}
return ReplacedNode(replace(&mut child.frame_tree, new_child));
}
}
@ -137,15 +156,23 @@ impl FrameTree {
fn to_sendable(&self) -> SendableFrameTree {
let sendable_frame_tree = SendableFrameTree {
pipeline: self.pipeline.to_sendable(),
children: self.children.iter().map(|frame_tree| frame_tree.to_sendable()).collect(),
pipeline: {
// NOTE: work around borrowchk issues
let tmp = self.pipeline.borrow();
tmp.get().borrow().to_sendable()
},
children: {
// NOTE: work around borrowchk issues
let tmp = self.children.borrow();
tmp.get().iter().map(|frame_tree| frame_tree.to_sendable()).collect()
},
};
sendable_frame_tree
}
pub fn iter(@mut self) -> FrameTreeIterator {
pub fn iter(&self) -> FrameTreeIterator {
FrameTreeIterator {
stack: ~[self],
stack: ~[Rc::new(self.clone())],
}
}
}
@ -153,7 +180,7 @@ impl FrameTree {
impl ChildFrameTree {
fn to_sendable(&self) -> SendableChildFrameTree {
SendableChildFrameTree {
frame_tree: self.frame_tree.to_sendable(),
frame_tree: self.frame_tree.borrow().to_sendable(),
rect: self.rect,
}
}
@ -163,15 +190,19 @@ impl ChildFrameTree {
/// Note that this iterator should _not_ be used to mutate nodes _during_
/// iteration. Mutating nodes once the iterator is out of scope is OK.
pub struct FrameTreeIterator {
priv stack: ~[@mut FrameTree],
priv stack: ~[Rc<FrameTree>],
}
impl Iterator<@mut FrameTree> for FrameTreeIterator {
fn next(&mut self) -> Option<@mut FrameTree> {
impl Iterator<Rc<FrameTree>> for FrameTreeIterator {
fn next(&mut self) -> Option<Rc<FrameTree>> {
if !self.stack.is_empty() {
let next = self.stack.pop();
for &ChildFrameTree { frame_tree, .. } in next.children.rev_iter() {
self.stack.push(frame_tree);
{
// NOTE: work around borrowchk issues
let tmp = next.borrow().children.borrow();
for cft in tmp.get().rev_iter() {
self.stack.push(cft.frame_tree.clone());
}
}
Some(next)
} else {
@ -183,15 +214,15 @@ impl Iterator<@mut FrameTree> for FrameTreeIterator {
/// Represents the portion of a page that is changing in navigating.
struct FrameChange {
before: Option<PipelineId>,
after: @mut FrameTree,
after: Rc<FrameTree>,
navigation_type: NavigationType,
}
/// Stores the Id's of the pipelines previous and next in the browser's history
struct NavigationContext {
previous: ~[@mut FrameTree],
next: ~[@mut FrameTree],
current: Option<@mut FrameTree>,
previous: ~[Rc<FrameTree>],
next: ~[Rc<FrameTree>],
current: Option<Rc<FrameTree>>,
}
impl NavigationContext {
@ -206,39 +237,45 @@ 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. */
pub fn back(&mut self) -> @mut FrameTree {
pub fn back(&mut self) -> Rc<FrameTree> {
self.next.push(self.current.take_unwrap());
self.current = Some(self.previous.pop());
self.current.unwrap()
let prev = self.previous.pop();
self.current = Some(prev.clone());
prev
}
pub fn forward(&mut self) -> @mut FrameTree {
pub fn forward(&mut self) -> Rc<FrameTree> {
self.previous.push(self.current.take_unwrap());
self.current = Some(self.next.pop());
self.current.unwrap()
let next = self.next.pop();
self.current = Some(next.clone());
next
}
/// Loads a new set of page frames, returning all evicted frame trees
pub fn load(&mut self, frame_tree: @mut FrameTree) -> ~[@mut FrameTree] {
debug!("navigating to {:?}", frame_tree.pipeline.id);
pub fn load(&mut self, frame_tree: Rc<FrameTree>) -> ~[Rc<FrameTree>] {
debug!("navigating to {:?}", {
// NOTE: work around borrowchk issues
let tmp = frame_tree.borrow().pipeline.borrow();
tmp.get().borrow().id
});
let evicted = replace(&mut self.next, ~[]);
if self.current.is_some() {
self.previous.push(self.current.take_unwrap());
}
self.current = Some(frame_tree);
self.current = Some(frame_tree.clone());
evicted
}
/// Returns the frame trees whose keys are pipeline_id.
pub fn find_all(&mut self, pipeline_id: PipelineId) -> ~[@mut FrameTree] {
pub fn find_all(&mut self, pipeline_id: PipelineId) -> ~[Rc<FrameTree>] {
let from_current = self.current.iter().filter_map(|frame_tree| {
frame_tree.find(pipeline_id)
frame_tree.borrow().find(pipeline_id)
});
let from_next = self.next.iter().filter_map(|frame_tree| {
frame_tree.find(pipeline_id)
frame_tree.borrow().find(pipeline_id)
});
let from_prev = self.previous.iter().filter_map(|frame_tree| {
frame_tree.find(pipeline_id)
frame_tree.borrow().find(pipeline_id)
});
from_prev.chain(from_current).chain(from_next).collect()
}
@ -250,7 +287,7 @@ impl NavigationContext {
let mut all_contained = from_prev.chain(from_current).chain(from_next);
all_contained.any(|frame_tree| {
frame_tree.contains(pipeline_id)
frame_tree.borrow().contains(pipeline_id)
})
}
}
@ -304,15 +341,15 @@ impl Constellation {
/// 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<@mut FrameTree> {
fn current_frame<'a>(&'a self) -> &'a Option<Rc<FrameTree>> {
&self.navigation_context.current
}
/// Returns both the navigation context and pending frame trees whose keys are pipeline_id.
pub fn find_all(&mut self, pipeline_id: PipelineId) -> ~[@mut FrameTree] {
pub fn find_all(&mut self, pipeline_id: PipelineId) -> ~[Rc<FrameTree>] {
let matching_navi_frames = self.navigation_context.find_all(pipeline_id);
let matching_pending_frames = self.pending_frames.iter().filter_map(|frame_change| {
frame_change.after.find(pipeline_id)
frame_change.after.borrow().find(pipeline_id)
});
matching_navi_frames.move_iter().chain(matching_pending_frames).collect()
}
@ -376,7 +413,7 @@ impl Constellation {
fn handle_exit(&self) {
for (_id, ref pipeline) in self.pipelines.iter() {
pipeline.exit();
pipeline.borrow().exit();
}
self.image_cache_task.exit();
self.resource_task.send(resource_task::Exit);
@ -397,62 +434,64 @@ impl Constellation {
let old_pipeline = match self.pipelines.find(&pipeline_id) {
None => return, // already failed?
Some(id) => *id
Some(id) => id.clone()
};
old_pipeline.script_chan.try_send(ExitPipelineMsg(pipeline_id));
old_pipeline.render_chan.try_send(render_task::ExitMsg(None));
old_pipeline.layout_chan.try_send(layout_interface::ExitNowMsg);
old_pipeline.borrow().script_chan.try_send(ExitPipelineMsg(pipeline_id));
old_pipeline.borrow().render_chan.try_send(render_task::ExitMsg(None));
old_pipeline.borrow().layout_chan.try_send(layout_interface::ExitNowMsg);
self.pipelines.remove(&pipeline_id);
let new_id = self.get_next_pipeline_id();
let pipeline = @mut Pipeline::create(new_id,
subpage_id,
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.resource_task.clone(),
self.profiler_chan.clone(),
self.window_size,
self.opts.clone());
self.pipelines.insert(new_id, pipeline);
let pipeline = Pipeline::create(new_id,
subpage_id,
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.resource_task.clone(),
self.profiler_chan.clone(),
self.window_size,
self.opts.clone());
let url = parse_url("about:failure", None);
pipeline.load(url);
let pipeline_wrapped = Rc::new(pipeline);
self.pending_frames.push(FrameChange{
before: Some(pipeline_id),
after: @mut FrameTree {
pipeline: pipeline,
parent: None,
children: ~[],
},
after: Rc::new(FrameTree {
pipeline: RefCell::new(pipeline_wrapped.clone()),
parent: RefCell::new(None),
children: RefCell::new(~[]),
}),
navigation_type: constellation_msg::Navigate,
});
self.pipelines.insert(pipeline_id, pipeline_wrapped);
}
fn handle_init_load(&mut self, url: Url) {
let pipeline = @mut Pipeline::create(self.get_next_pipeline_id(),
None,
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.resource_task.clone(),
self.profiler_chan.clone(),
self.window_size,
self.opts.clone());
let pipeline = Pipeline::create(self.get_next_pipeline_id(),
None,
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.resource_task.clone(),
self.profiler_chan.clone(),
self.window_size,
self.opts.clone());
pipeline.load(url);
let pipeline_wrapped = Rc::new(pipeline);
self.pending_frames.push(FrameChange {
before: None,
after: @mut FrameTree {
pipeline: pipeline,
parent: None,
children: ~[],
},
after: Rc::new(FrameTree {
pipeline: RefCell::new(pipeline_wrapped.clone()),
parent: RefCell::new(None),
children: RefCell::new(~[]),
}),
navigation_type: constellation_msg::Load,
});
self.pipelines.insert(pipeline.id, pipeline);
self.pipelines.insert(pipeline_wrapped.borrow().id, pipeline_wrapped);
}
fn handle_frame_rect_msg(&mut self, pipeline_id: PipelineId, subpage_id: SubpageId, rect: Rect<f32>) {
@ -461,7 +500,10 @@ impl Constellation {
// Returns true if a child frame tree's subpage id matches the given subpage id
let subpage_eq = |child_frame_tree: & &mut ChildFrameTree| {
child_frame_tree.frame_tree.pipeline.subpage_id.expect("Constellation:
// NOTE: work around borrowchk issues
let tmp = child_frame_tree.frame_tree.borrow().pipeline.borrow();
tmp.get().borrow().
subpage_id.expect("Constellation:
child frame does not have a subpage id. This should not be possible.")
== subpage_id
};
@ -471,19 +513,23 @@ impl Constellation {
// resize happens immediately.
let update_child_rect = |child_frame_tree: &mut ChildFrameTree, is_active: bool| {
child_frame_tree.rect = Some(rect.clone());
let pipeline = &child_frame_tree.frame_tree.pipeline;
if !already_sent.contains(&pipeline.id) {
// NOTE: work around borrowchk issues
let pipeline = &child_frame_tree.frame_tree.borrow().pipeline.borrow();
if !already_sent.contains(&pipeline.get().borrow().id) {
let Size2D { width, height } = rect.size;
if is_active {
let pipeline = pipeline.get().borrow();
pipeline.script_chan.send(ResizeMsg(pipeline.id, Size2D {
width: width as uint,
height: height as uint
}));
self.compositor_chan.send(SetLayerClipRect(pipeline.id, rect));
} else {
let pipeline = pipeline.get().borrow();
pipeline.script_chan.send(ResizeInactiveMsg(pipeline.id,
Size2D(width as uint, height as uint)));
}
let pipeline = pipeline.get().borrow();
already_sent.insert(pipeline.id);
}
};
@ -491,10 +537,11 @@ impl Constellation {
// If the subframe is in the current frame tree, the compositor needs the new size
for current_frame in self.current_frame().iter() {
debug!("Constellation: Sending size for frame in current frame tree.");
let source_frame = current_frame.find(pipeline_id);
let source_frame = current_frame.borrow().find(pipeline_id);
for source_frame in source_frame.iter() {
let found_child = source_frame.children.mut_iter()
.find(|child| subpage_eq(child));
// NOTE: work around borrowchk issues
let mut tmp = source_frame.borrow().children.borrow_mut();
let found_child = tmp.get().mut_iter().find(|child| subpage_eq(child));
found_child.map(|child| update_child_rect(child, true));
}
}
@ -502,8 +549,9 @@ impl Constellation {
// Update all frames with matching pipeline- and subpage-ids
let frames = self.find_all(pipeline_id);
for frame_tree in frames.iter() {
let found_child = frame_tree.children.mut_iter()
.find(|child| subpage_eq(child));
// NOTE: work around borrowchk issues
let mut tmp = frame_tree.borrow().children.borrow_mut();
let found_child = tmp.get().mut_iter().find(|child| subpage_eq(child));
found_child.map(|child| update_child_rect(child, false));
}
@ -526,10 +574,10 @@ impl Constellation {
// or a new url entered.
// Start by finding the frame trees matching the pipeline id,
// and add the new pipeline to their sub frames.
let frame_trees: ~[@mut FrameTree] = {
let frame_trees: ~[Rc<FrameTree>] = {
let matching_navi_frames = self.navigation_context.find_all(source_pipeline_id);
let matching_pending_frames = self.pending_frames.iter().filter_map(|frame_change| {
frame_change.after.find(source_pipeline_id)
frame_change.after.borrow().find(source_pipeline_id)
});
matching_navi_frames.move_iter().chain(matching_pending_frames).collect()
};
@ -544,18 +592,18 @@ impl Constellation {
// Compare the pipeline's url to the new url. If the origin is the same,
// then reuse the script task in creating the new pipeline
let source_pipeline = *self.pipelines.find(&source_pipeline_id).expect("Constellation:
let source_pipeline = self.pipelines.find(&source_pipeline_id).expect("Constellation:
source Id of LoadIframeUrlMsg does have an associated pipeline in
constellation. This should be impossible.");
constellation. This should be impossible.").clone();
let source_url = source_pipeline.url.clone().expect("Constellation: LoadUrlIframeMsg's
let source_url = source_pipeline.borrow().url.get().clone().expect("Constellation: LoadUrlIframeMsg's
source's Url is None. There should never be a LoadUrlIframeMsg from a pipeline
that was never given a url to load.");
let same_script = (source_url.host == url.host &&
source_url.port == url.port) && sandbox == IFrameUnsandboxed;
// FIXME(tkuehn): Need to follow the standardized spec for checking same-origin
let pipeline = @mut if same_script {
let pipeline = if same_script {
debug!("Constellation: loading same-origin iframe at {:?}", url);
// Reuse the script task if same-origin url's
Pipeline::with_script(next_pipeline_id,
@ -565,7 +613,7 @@ impl Constellation {
self.image_cache_task.clone(),
self.profiler_chan.clone(),
self.opts.clone(),
source_pipeline)
source_pipeline.clone())
} else {
debug!("Constellation: loading cross-origin iframe at {:?}", url);
// Create a new script task if not same-origin url's
@ -582,24 +630,27 @@ impl Constellation {
debug!("Constellation: sending load msg to pipeline {:?}", pipeline.id);
pipeline.load(url);
let pipeline_wrapped = Rc::new(pipeline);
let rect = self.pending_sizes.pop(&(source_pipeline_id, subpage_id));
for frame_tree in frame_trees.iter() {
frame_tree.children.push(ChildFrameTree {
frame_tree: @mut FrameTree {
pipeline: pipeline,
parent: Some(source_pipeline),
children: ~[],
},
// NOTE: work around borrowchk issues
let mut tmp = frame_tree.borrow().children.borrow_mut();
tmp.get().push(ChildFrameTree {
frame_tree: Rc::new(FrameTree {
pipeline: RefCell::new(pipeline_wrapped.clone()),
parent: RefCell::new(Some(source_pipeline.clone())),
children: RefCell::new(~[]),
}),
rect: rect,
});
}
self.pipelines.insert(pipeline.id, pipeline);
self.pipelines.insert(pipeline_wrapped.borrow().id, pipeline_wrapped);
}
fn handle_load_url_msg(&mut self, source_id: PipelineId, url: Url) {
debug!("Constellation: received message to load {:s}", url.to_str());
// Make sure no pending page would be overridden.
let source_frame = self.current_frame().get_ref().find(source_id).expect(
let source_frame = self.current_frame().get_ref().borrow().find(source_id).expect(
"Constellation: received a LoadUrlMsg from a pipeline_id associated
with a pipeline not in the active frame tree. This should be
impossible.");
@ -608,10 +659,10 @@ impl Constellation {
let old_id = frame_change.before.expect("Constellation: Received load msg
from pipeline, but there is no currently active page. This should
be impossible.");
let changing_frame = self.current_frame().get_ref().find(old_id).expect("Constellation:
let changing_frame = self.current_frame().get_ref().borrow().find(old_id).expect("Constellation:
Pending change has non-active source pipeline. This should be
impossible.");
if changing_frame.contains(source_id) || source_frame.contains(old_id) {
if changing_frame.borrow().contains(source_id) || source_frame.borrow().contains(old_id) {
// id that sent load msg is being changed already; abort
return;
}
@ -619,32 +670,35 @@ impl Constellation {
// Being here means either there are no pending frames, or none of the pending
// changes would be overriden by changing the subframe associated with source_id.
let parent = source_frame.parent.clone();
let subpage_id = source_frame.pipeline.subpage_id;
let parent = source_frame.borrow().parent.clone();
// NOTE: work around borrowchk issues
let tmp = source_frame.borrow().pipeline.borrow();
let subpage_id = tmp.get().borrow().subpage_id;
let next_pipeline_id = self.get_next_pipeline_id();
let pipeline = @mut Pipeline::create(next_pipeline_id,
subpage_id,
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.resource_task.clone(),
self.profiler_chan.clone(),
self.window_size,
self.opts.clone());
let pipeline = Pipeline::create(next_pipeline_id,
subpage_id,
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.resource_task.clone(),
self.profiler_chan.clone(),
self.window_size,
self.opts.clone());
pipeline.load(url);
let pipeline_wrapped = Rc::new(pipeline);
self.pending_frames.push(FrameChange{
before: Some(source_id),
after: @mut FrameTree {
pipeline: pipeline,
after: Rc::new(FrameTree {
pipeline: RefCell::new(pipeline_wrapped.clone()),
parent: parent,
children: ~[],
},
children: RefCell::new(~[]),
}),
navigation_type: constellation_msg::Load,
});
self.pipelines.insert(pipeline.id, pipeline);
self.pipelines.insert(pipeline_wrapped.borrow().id, pipeline_wrapped);
}
fn handle_navigate_msg(&mut self, direction: constellation_msg::NavigationDirection) {
@ -661,8 +715,10 @@ impl Constellation {
return;
} else {
let old = self.current_frame().get_ref();
for frame in old.iter() {
frame.pipeline.revoke_paint_permission();
for frame in old.borrow().iter() {
// NOTE: work around borrowchk issues
let tmp = frame.borrow().pipeline.borrow();
tmp.get().borrow().revoke_paint_permission();
}
}
self.navigation_context.forward()
@ -673,17 +729,20 @@ impl Constellation {
return;
} else {
let old = self.current_frame().get_ref();
for frame in old.iter() {
frame.pipeline.revoke_paint_permission();
for frame in old.borrow().iter() {
// NOTE: work around borrowchk issues
let tmp = frame.borrow().pipeline.borrow();
tmp.get().borrow().revoke_paint_permission();
}
}
self.navigation_context.back()
}
};
for frame in destination_frame.iter() {
let pipeline = &frame.pipeline;
pipeline.reload();
for frame in destination_frame.borrow().iter() {
// NOTE: work around borrowchk issues
let pipeline = &frame.borrow().pipeline.borrow();
pipeline.get().borrow().reload();
}
self.grant_paint_permission(destination_frame, constellation_msg::Navigate);
@ -695,13 +754,15 @@ impl Constellation {
// from a pending frame. The only time that we will grant paint permission is
// when the message originates from a pending frame or the current frame.
for &current_frame in self.current_frame().iter() {
for current_frame in self.current_frame().iter() {
// Messages originating in the current frame are not navigations;
// TODO(tkuehn): In fact, this kind of message might be provably
// impossible to occur.
if current_frame.contains(pipeline_id) {
for frame in current_frame.iter() {
frame.pipeline.grant_paint_permission();
if current_frame.borrow().contains(pipeline_id) {
for frame in current_frame.borrow().iter() {
// NOTE: work around borrowchk issues
let tmp = frame.borrow().pipeline.borrow();
tmp.get().borrow().grant_paint_permission();
}
return;
}
@ -711,53 +772,87 @@ impl Constellation {
// If it is not found, it simply means that this pipeline will not receive
// permission to paint.
let pending_index = self.pending_frames.iter().rposition(|frame_change| {
frame_change.after.pipeline.id == pipeline_id
// NOTE: work around borrowchk issues
let tmp = frame_change.after.borrow().pipeline.borrow();
tmp.get().borrow().id == pipeline_id
});
for &pending_index in pending_index.iter() {
let frame_change = self.pending_frames.swap_remove(pending_index);
let to_add = frame_change.after;
let to_add = frame_change.after.clone();
// Create the next frame tree that will be given to the compositor
let next_frame_tree = match to_add.parent {
None => to_add, // to_add is the root
Some(_parent) => @mut (*self.current_frame().unwrap()).clone(),
// NOTE: work around borrowchk issues
let tmp = to_add.borrow().parent.clone();
let tmp = tmp.borrow();
let next_frame_tree = if tmp.get().is_some() {
// NOTE: work around borrowchk issues
let tmp = self.current_frame().get_ref();
tmp.clone()
} else {
to_add.clone()
};
// If there are frames to revoke permission from, do so now.
match frame_change.before {
Some(revoke_id) => {
debug!("Constellation: revoking permission from {:?}", revoke_id);
let current_frame = self.current_frame().unwrap();
let current_frame = self.current_frame().get_ref();
let to_revoke = current_frame.find(revoke_id).expect(
let to_revoke = current_frame.borrow().find(revoke_id).expect(
"Constellation: pending frame change refers to an old
frame not contained in the current frame. This is a bug");
for frame in to_revoke.iter() {
frame.pipeline.revoke_paint_permission();
for frame in to_revoke.borrow().iter() {
// NOTE: work around borrowchk issues
let tmp = frame.borrow().pipeline.borrow();
tmp.get().borrow().revoke_paint_permission();
}
// If to_add is not the root frame, then replace revoked_frame with it.
// This conveniently keeps scissor rect size intact.
if to_add.parent.is_some() {
debug!("Constellation: replacing {:?} with {:?} in {:?}",
revoke_id, to_add.pipeline.id, next_frame_tree.pipeline.id);
next_frame_tree.replace_child(revoke_id, to_add);
// NOTE: work around borrowchk issue
let mut flag = false;
{
// NOTE: work around borrowchk issue
let tmp = to_add.borrow().parent.borrow();
if tmp.get().is_some() {
debug!("Constellation: replacing {:?} with {:?} in {:?}",
revoke_id, {
// NOTE: work around borrowchk issues
let tmp = to_add.borrow().pipeline.borrow();
tmp.get().borrow().id
}, {
// NOTE: work around borrowchk issues
let tmp = next_frame_tree.borrow().pipeline.borrow();
tmp.get().borrow().id
});
flag = true;
}
}
if flag {
next_frame_tree.borrow().replace_child(revoke_id, to_add);
}
}
None => {
// Add to_add to parent's children, if it is not the root
let parent = &to_add.parent;
for parent in parent.iter() {
let subpage_id = to_add.pipeline.subpage_id.expect("Constellation:
let parent = &to_add.borrow().parent;
// NOTE: work around borrowchk issue
let tmp = parent.borrow();
for parent in tmp.get().iter() {
// NOTE: work around borrowchk issues
let tmp = to_add.borrow().pipeline.borrow();
let subpage_id = tmp.get().borrow().subpage_id
.expect("Constellation:
Child frame's subpage id is None. This should be impossible.");
let rect = self.pending_sizes.pop(&(parent.id, subpage_id));
let parent = next_frame_tree.find(parent.id).expect(
let rect = self.pending_sizes.pop(&(parent.borrow().id, subpage_id));
let parent = next_frame_tree.borrow().find(parent.borrow().id).expect(
"Constellation: pending frame has a parent frame that is not
active. This is a bug.");
parent.children.push(ChildFrameTree {
frame_tree: to_add,
// NOTE: work around borrowchk issue
let mut tmp = parent.borrow().children.borrow_mut();
tmp.get().push(ChildFrameTree {
frame_tree: to_add.clone(),
rect: rect,
});
}
@ -771,14 +866,19 @@ impl Constellation {
/// Called when the window is resized.
fn handle_resized_window_msg(&mut self, new_size: Size2D<uint>) {
let mut already_seen = HashSet::new();
for &@FrameTree { pipeline: pipeline, .. } in self.current_frame().iter() {
for frame_tree in self.current_frame().iter() {
debug!("constellation sending resize message to active frame");
// NOTE: work around borrowchk issues
let tmp = frame_tree.borrow().pipeline.borrow();
let pipeline = tmp.get().borrow();
pipeline.script_chan.try_send(ResizeMsg(pipeline.id, new_size));
already_seen.insert(pipeline.id);
}
for frame_tree in self.navigation_context.previous.iter()
.chain(self.navigation_context.next.iter()) {
let pipeline = &frame_tree.pipeline;
// NOTE: work around borrowchk issues
let tmp = frame_tree.borrow().pipeline.borrow();
let pipeline = &tmp.get().borrow();
if !already_seen.contains(&pipeline.id) {
debug!("constellation sending resize message to inactive frame");
pipeline.script_chan.try_send(ResizeInactiveMsg(pipeline.id, new_size));
@ -789,10 +889,15 @@ impl Constellation {
// If there are any pending outermost frames, then tell them to resize. (This is how the
// initial window size gets sent to the first page loaded, giving it permission to reflow.)
for change in self.pending_frames.iter() {
let frame_tree = change.after;
if frame_tree.parent.is_none() {
let frame_tree = change.after.borrow();
// NOTE: work around borrowchk issue
let tmp = frame_tree.parent.borrow();
if tmp.get().is_none() {
debug!("constellation sending resize message to pending outer frame");
frame_tree.pipeline.script_chan.send(ResizeMsg(frame_tree.pipeline.id, new_size))
// NOTE: work around borrowchk issues
let tmp = frame_tree.pipeline.borrow();
let pipeline = tmp.get().borrow();
pipeline.script_chan.send(ResizeMsg(pipeline.id, new_size))
}
}
@ -800,31 +905,38 @@ impl Constellation {
}
// Close all pipelines at and beneath a given frame
fn close_pipelines(&mut self, frame_tree: @mut FrameTree) {
fn close_pipelines(&mut self, frame_tree: Rc<FrameTree>) {
// TODO(tkuehn): should only exit once per unique script task,
// and then that script task will handle sub-exits
for @FrameTree { pipeline, .. } in frame_tree.iter() {
for frame_tree in frame_tree.borrow().iter() {
// NOTE: work around borrowchk issues
let tmp = frame_tree.borrow().pipeline.borrow();
let pipeline = tmp.get().borrow();
pipeline.exit();
self.pipelines.remove(&pipeline.id);
}
}
fn handle_evicted_frames(&mut self, evicted: ~[@mut FrameTree]) {
for &frame_tree in evicted.iter() {
if !self.navigation_context.contains(frame_tree.pipeline.id) {
self.close_pipelines(frame_tree);
fn handle_evicted_frames(&mut self, evicted: ~[Rc<FrameTree>]) {
for frame_tree in evicted.iter() {
// NOTE: work around borrowchk issues
let tmp = frame_tree.borrow().pipeline.borrow();
if !self.navigation_context.contains(tmp.get().borrow().id) {
self.close_pipelines(frame_tree.clone());
} else {
self.handle_evicted_frames(frame_tree.children.iter()
.map(|child| child.frame_tree)
.collect());
// NOTE: work around borrowchk issue
let tmp = frame_tree.borrow().children.borrow();
let mut frames = tmp.get().iter()
.map(|child| child.frame_tree.clone());
self.handle_evicted_frames(frames.collect());
}
}
}
// Grants a frame tree permission to paint; optionally updates navigation to reflect a new page
fn grant_paint_permission(&mut self, frame_tree: @mut FrameTree, navigation_type: NavigationType) {
fn grant_paint_permission(&mut self, frame_tree: Rc<FrameTree>, navigation_type: NavigationType) {
// Give permission to paint to the new frame and all child frames
self.set_ids(frame_tree);
self.set_ids(&frame_tree);
// Don't call navigation_context.load() on a Navigate type (or None, as in the case of
// parsed iframes that finish loading)
@ -837,14 +949,17 @@ impl Constellation {
}
}
fn set_ids(&self, frame_tree: @mut FrameTree) {
fn set_ids(&self, frame_tree: &Rc<FrameTree>) {
let (port, chan) = Chan::new();
debug!("Constellation sending SetIds");
self.compositor_chan.send(SetIds(frame_tree.to_sendable(), chan, self.chan.clone()));
self.compositor_chan.send(SetIds(frame_tree.borrow().to_sendable(), chan, self.chan.clone()));
match port.recv_opt() {
Some(()) => {
for frame in frame_tree.iter() {
frame.pipeline.grant_paint_permission();
let mut iter = frame_tree.borrow().iter();
for frame in iter {
// NOTE: work around borrowchk issues
let tmp = frame.borrow().pipeline.borrow();
tmp.get().borrow().grant_paint_permission();
}
}
None => {} // message has been discarded, probably shutting down

View file

@ -19,6 +19,10 @@ use servo_msg::constellation_msg::{ConstellationChan, Failure, PipelineId, Subpa
use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::ResourceTask;
use servo_util::time::ProfilerChan;
use std::cell::RefCell;
//FIXME: switch to std::rc when we upgrade Rust
use layers::temp_rc::Rc;
//use std::rc::Rc;
/// A uniquely-identifiable pipeline of script task, layout task, and render task.
pub struct Pipeline {
@ -30,7 +34,7 @@ pub struct Pipeline {
layout_shutdown_port: Port<()>,
render_shutdown_port: Port<()>,
/// The most recently loaded url
url: Option<Url>,
url: RefCell<Option<Url>>,
}
/// The subset of the pipeline that is needed for layer composition.
@ -51,7 +55,7 @@ impl Pipeline {
image_cache_task: ImageCacheTask,
profiler_chan: ProfilerChan,
opts: Opts,
script_pipeline: &Pipeline)
script_pipeline: Rc<Pipeline>)
-> Pipeline {
let (layout_port, layout_chan) = LayoutChan::new();
let (render_port, render_chan) = RenderChan::new();
@ -77,7 +81,7 @@ impl Pipeline {
layout_chan.clone(),
constellation_chan,
failure,
script_pipeline.script_chan.clone(),
script_pipeline.borrow().script_chan.clone(),
render_chan.clone(),
image_cache_task.clone(),
opts.clone(),
@ -85,16 +89,16 @@ impl Pipeline {
layout_shutdown_chan);
let new_layout_info = NewLayoutInfo {
old_id: script_pipeline.id.clone(),
old_id: script_pipeline.borrow().id.clone(),
new_id: id,
layout_chan: layout_chan.clone(),
};
script_pipeline.script_chan.send(AttachLayoutMsg(new_layout_info));
script_pipeline.borrow().script_chan.send(AttachLayoutMsg(new_layout_info));
Pipeline::new(id,
subpage_id,
script_pipeline.script_chan.clone(),
script_pipeline.borrow().script_chan.clone(),
layout_chan,
render_chan,
layout_shutdown_port,
@ -180,12 +184,12 @@ impl Pipeline {
render_chan: render_chan,
layout_shutdown_port: layout_shutdown_port,
render_shutdown_port: render_shutdown_port,
url: None,
url: RefCell::new(None),
}
}
pub fn load(&mut self, url: Url) {
self.url = Some(url.clone());
pub fn load(&self, url: Url) {
self.url.set(Some(url.clone()));
self.script_chan.send(LoadMsg(self.id, url));
}
@ -198,8 +202,8 @@ impl Pipeline {
self.render_chan.try_send(PaintPermissionRevoked);
}
pub fn reload(&mut self) {
self.url.clone().map(|url| {
pub fn reload(&self) {
self.url.get().clone().map(|url| {
self.load(url);
});
}

View file

@ -1,59 +0,0 @@
/* 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/. */
//! A windowing implementation using shared OpenGL textures.
///
/// In this setup, Servo renders to an OpenGL texture and uses IPC to share that texture with
/// another application. It also uses IPC to handle events.
///
/// This is designed for sandboxing scenarios which the OpenGL graphics driver is either sandboxed
/// along with the Servo process or trusted. If the OpenGL driver itself is untrusted, then this
/// windowing implementation is not appropriate.
use windowing::{CompositeCallback, LoadUrlCallback, ResizeCallback};
use geom::size::Size2D;
use sharegl::base::ShareContext;
use sharegl::platform::Context;
/// A structure responsible for setting up and tearing down the entire windowing system.
pub struct Application;
impl ApplicationMethods for Application {
pub fn new() -> Application {
Application
}
}
/// The type of a window.
pub struct Window(Context);
impl WindowingMethods<Application> for Window {
/// Creates a new window.
pub fn new(_: &Application) -> @mut Window {
let share_context: Context = ShareContext::new(Size2D(800, 600));
println(format!("Sharing ID is {:d}", share_context.id()));
@mut Window(share_context)
}
/// Returns the size of the window.
pub fn size(&mut self) -> Size2D<f32> {
Size2D(800.0, 600.0)
}
/// Presents the window to the screen (perhaps by page flipping).
pub fn present(&mut self) {
(*self).flush();
}
/// Registers a callback to run when a resize event occurs.
pub fn set_resize_callback(&mut self, _: ResizeCallback) {}
/// Registers a callback to run when a new URL is to be loaded.
pub fn set_load_url_callback(&mut self, _: LoadUrlCallback) {}
/// Returns the next event.
pub fn check_loop(@mut self) -> bool { false }
}

View file

@ -4,19 +4,15 @@
//! Platform-specific functionality for Servo.
#[cfg(not(shared_gl_windowing), target_os="android")]
#[cfg(target_os="android")]
pub use platform::common::glut_windowing::{Application, Window};
#[cfg(not(shared_gl_windowing), not(target_os="android"))]
#[cfg(not(target_os="android"))]
pub use platform::common::glfw_windowing::{Application, Window};
#[cfg(shared_gl_windowing)]
pub use platform::common::shared_gl_windowing::{Application, Window};
pub mod common {
#[cfg(not(shared_gl_windowing), target_os="android")]
#[cfg(target_os="android")]
pub mod glut_windowing;
#[cfg(not(shared_gl_windowing), not(target_os="android"))]
#[cfg(not(target_os="android"))]
pub mod glfw_windowing;
#[cfg(shared_gl_windowing)]
pub mod shared_gl_windowing;
}

View file

@ -27,4 +27,3 @@ pub mod time;
pub mod url;
pub mod vec;
pub mod workqueue;

@ -1 +1 @@
Subproject commit a6cdac57469b61266bb9abf7551d24f93fd2bb98
Subproject commit 4d8863bc6d8c2b192b2adb40ef124c0e68999ef0