mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
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:
commit
006237fed3
8 changed files with 425 additions and 327 deletions
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ¤t_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
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,4 +27,3 @@ pub mod time;
|
|||
pub mod url;
|
||||
pub mod vec;
|
||||
pub mod workqueue;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit a6cdac57469b61266bb9abf7551d24f93fd2bb98
|
||||
Subproject commit 4d8863bc6d8c2b192b2adb40ef124c0e68999ef0
|
Loading…
Add table
Add a link
Reference in a new issue