mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
De-@mut the FrameTree.
This commit is contained in:
parent
683c2fada1
commit
347bbd2883
5 changed files with 366 additions and 219 deletions
|
@ -39,12 +39,16 @@ use servo_util::{time, url};
|
||||||
use std::comm::Port;
|
use std::comm::Port;
|
||||||
use std::num::Orderable;
|
use std::num::Orderable;
|
||||||
use std::path::Path;
|
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 {
|
pub struct IOCompositor {
|
||||||
/// The application window.
|
/// The application window.
|
||||||
window: Rc<Window>,
|
window: rc::Rc<Window>,
|
||||||
|
|
||||||
/// The port on which we receive messages.
|
/// The port on which we receive messages.
|
||||||
port: Port<Msg>,
|
port: Port<Msg>,
|
||||||
|
@ -53,7 +57,7 @@ pub struct IOCompositor {
|
||||||
context: RenderContext,
|
context: RenderContext,
|
||||||
|
|
||||||
/// The root ContainerLayer.
|
/// The root ContainerLayer.
|
||||||
root_layer: @mut ContainerLayer,
|
root_layer: Rc<ContainerLayer>,
|
||||||
|
|
||||||
/// The canvas to paint a page.
|
/// The canvas to paint a page.
|
||||||
scene: Scene,
|
scene: Scene,
|
||||||
|
@ -116,13 +120,13 @@ impl IOCompositor {
|
||||||
port: Port<Msg>,
|
port: Port<Msg>,
|
||||||
constellation_chan: ConstellationChan,
|
constellation_chan: ConstellationChan,
|
||||||
profiler_chan: ProfilerChan) -> IOCompositor {
|
profiler_chan: ProfilerChan) -> IOCompositor {
|
||||||
let window: Rc<Window> = WindowMethods::new(app);
|
let window: rc::Rc<Window> = WindowMethods::new(app);
|
||||||
|
|
||||||
// Create an initial layer tree.
|
// Create an initial layer tree.
|
||||||
//
|
//
|
||||||
// TODO: There should be no initial layer tree until the renderer creates one from the display
|
// 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.
|
// 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();
|
let window_size = window.borrow().size();
|
||||||
|
|
||||||
IOCompositor {
|
IOCompositor {
|
||||||
|
@ -130,7 +134,7 @@ impl IOCompositor {
|
||||||
port: port,
|
port: port,
|
||||||
opts: opts,
|
opts: opts,
|
||||||
context: rendergl::init_render_context(),
|
context: rendergl::init_render_context(),
|
||||||
root_layer: root_layer,
|
root_layer: root_layer.clone(),
|
||||||
scene: Scene(ContainerLayerKind(root_layer), window_size, identity()),
|
scene: Scene(ContainerLayerKind(root_layer), window_size, identity()),
|
||||||
window_size: Size2D(window_size.width as uint, window_size.height as uint),
|
window_size: Size2D(window_size.width as uint, window_size.height as uint),
|
||||||
graphics_context: CompositorTask::create_graphics_context(),
|
graphics_context: CompositorTask::create_graphics_context(),
|
||||||
|
@ -317,16 +321,22 @@ impl IOCompositor {
|
||||||
response_chan.send(());
|
response_chan.send(());
|
||||||
|
|
||||||
// This assumes there is at most one child, which should be the case.
|
// This assumes there is at most one child, which should be the case.
|
||||||
match self.root_layer.first_child {
|
// NOTE: work around borrowchk
|
||||||
Some(old_layer) => self.root_layer.remove_child(old_layer),
|
{
|
||||||
None => {}
|
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,
|
let layer = CompositorLayer::from_frame_tree(frame_tree,
|
||||||
self.opts.tile_size,
|
self.opts.tile_size,
|
||||||
Some(10000000u),
|
Some(10000000u),
|
||||||
self.opts.cpu_painting);
|
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.
|
// If there's already a root layer, destroy it cleanly.
|
||||||
match self.compositor_layer {
|
match self.compositor_layer {
|
||||||
|
@ -360,13 +370,17 @@ impl IOCompositor {
|
||||||
Some(10000000u),
|
Some(10000000u),
|
||||||
self.opts.cpu_painting);
|
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.
|
let current_child = self.root_layer.borrow().first_child.borrow();
|
||||||
match current_child {
|
// This assumes there is at most one child, which should be the case.
|
||||||
Some(old_layer) => self.root_layer.remove_child(old_layer),
|
match *current_child.get() {
|
||||||
None => {}
|
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.compositor_layer = Some(new_layer);
|
||||||
|
|
||||||
self.ask_for_tiles();
|
self.ask_for_tiles();
|
||||||
|
@ -617,7 +631,7 @@ impl IOCompositor {
|
||||||
self.world_zoom = (self.world_zoom * magnification).max(&1.0);
|
self.world_zoom = (self.world_zoom * magnification).max(&1.0);
|
||||||
let world_zoom = self.world_zoom;
|
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
|
// Scroll as needed
|
||||||
let page_delta = Point2D(window_size.width as f32 * (1.0 / world_zoom - 1.0 / old_world_zoom) * 0.5,
|
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 script::script_task::SendEventMsg;
|
||||||
use servo_msg::compositor_msg::{LayerBuffer, LayerBufferSet, Epoch, Tile};
|
use servo_msg::compositor_msg::{LayerBuffer, LayerBufferSet, Epoch, Tile};
|
||||||
use servo_msg::constellation_msg::PipelineId;
|
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::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent};
|
||||||
use windowing::{MouseWindowMouseUpEvent};
|
use windowing::{MouseWindowMouseUpEvent};
|
||||||
use azure::azure_hl::Color;
|
use azure::azure_hl::Color;
|
||||||
|
@ -57,7 +60,7 @@ pub struct CompositorLayer {
|
||||||
|
|
||||||
/// The root layer of this CompositorLayer's layer tree. Buffers are collected
|
/// 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.
|
/// 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
|
/// When set to true, this layer is ignored by its parents. This is useful for
|
||||||
/// soft deletion or when waiting on a page size.
|
/// soft deletion or when waiting on a page size.
|
||||||
|
@ -80,10 +83,10 @@ pub struct CompositorLayer {
|
||||||
/// Helper struct for keeping CompositorLayer children organized.
|
/// Helper struct for keeping CompositorLayer children organized.
|
||||||
struct CompositorLayerChild {
|
struct CompositorLayerChild {
|
||||||
/// The child itself.
|
/// The child itself.
|
||||||
child: ~CompositorLayer,
|
child: ~CompositorLayer,
|
||||||
/// A ContainerLayer managed by the parent node. This deals with clipping and
|
/// A ContainerLayer managed by the parent node. This deals with clipping and
|
||||||
/// positioning, and is added above the child's layer tree.
|
/// 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
|
/// Helper enum for storing quadtrees. Either contains a quadtree, or contains
|
||||||
|
@ -123,7 +126,7 @@ impl CompositorLayer {
|
||||||
tile_size,
|
tile_size,
|
||||||
max_mem)),
|
max_mem)),
|
||||||
},
|
},
|
||||||
root_layer: @mut ContainerLayer(),
|
root_layer: Rc::new(ContainerLayer()),
|
||||||
hidden: true,
|
hidden: true,
|
||||||
epoch: Epoch(0),
|
epoch: Epoch(0),
|
||||||
scroll_behavior: Scroll,
|
scroll_behavior: Scroll,
|
||||||
|
@ -142,24 +145,23 @@ impl CompositorLayer {
|
||||||
let mut layer = CompositorLayer::new(pipeline, None, tile_size, max_mem, cpu_painting);
|
let mut layer = CompositorLayer::new(pipeline, None, tile_size, max_mem, cpu_painting);
|
||||||
layer.children = (children.move_iter().map(|child| {
|
layer.children = (children.move_iter().map(|child| {
|
||||||
let SendableChildFrameTree { frame_tree, rect } = child;
|
let SendableChildFrameTree { frame_tree, rect } = child;
|
||||||
let container = @mut ContainerLayer();
|
let container = Rc::new(ContainerLayer());
|
||||||
match rect {
|
match rect {
|
||||||
Some(rect) => {
|
Some(rect) => {
|
||||||
container.scissor = Some(rect);
|
container.borrow().scissor.set(Some(rect));
|
||||||
container.common.transform = identity().translate(rect.origin.x,
|
container.borrow().common.with_mut(|common| common.transform = identity().translate(rect.origin.x,
|
||||||
rect.origin.y,
|
rect.origin.y,
|
||||||
0f32);
|
0f32));
|
||||||
|
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let child_layer = ~CompositorLayer::from_frame_tree(frame_tree,
|
let child_layer = ~CompositorLayer::from_frame_tree(frame_tree,
|
||||||
tile_size,
|
tile_size,
|
||||||
max_mem,
|
max_mem,
|
||||||
cpu_painting);
|
cpu_painting);
|
||||||
container.add_child_start(ContainerLayerKind(child_layer.root_layer));
|
ContainerLayer::add_child_start(container.clone(), ContainerLayerKind(child_layer.root_layer.clone()));
|
||||||
|
|
||||||
CompositorLayerChild {
|
CompositorLayerChild {
|
||||||
child: child_layer,
|
child: child_layer,
|
||||||
container: container,
|
container: container,
|
||||||
|
@ -177,7 +179,9 @@ impl CompositorLayer {
|
||||||
-> bool {
|
-> bool {
|
||||||
let cursor = cursor - self.scroll_offset;
|
let cursor = cursor - self.scroll_offset;
|
||||||
for child in self.children.mut_iter().filter(|x| !x.child.hidden) {
|
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 => {
|
None => {
|
||||||
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
||||||
}
|
}
|
||||||
|
@ -213,9 +217,9 @@ impl CompositorLayer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.root_layer.common.set_transform(identity().translate(self.scroll_offset.x,
|
self.root_layer.borrow().common.with_mut(|common| common.set_transform(identity().translate(self.scroll_offset.x,
|
||||||
self.scroll_offset.y,
|
self.scroll_offset.y,
|
||||||
0.0));
|
0.0)));
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
FixedPosition => false, // Ignore this scroll event.
|
FixedPosition => false, // Ignore this scroll event.
|
||||||
|
@ -228,7 +232,9 @@ impl CompositorLayer {
|
||||||
pub fn send_mouse_event(&self, event: MouseWindowEvent, cursor: Point2D<f32>) {
|
pub fn send_mouse_event(&self, event: MouseWindowEvent, cursor: Point2D<f32>) {
|
||||||
let cursor = cursor - self.scroll_offset;
|
let cursor = cursor - self.scroll_offset;
|
||||||
for child in self.children.iter().filter(|&x| !x.child.hidden) {
|
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 => {
|
None => {
|
||||||
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
||||||
}
|
}
|
||||||
|
@ -287,7 +293,9 @@ impl CompositorLayer {
|
||||||
self.build_layer_tree(graphics_context);
|
self.build_layer_tree(graphics_context);
|
||||||
}
|
}
|
||||||
let transform = |x: &mut CompositorLayerChild| -> bool {
|
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) => {
|
Some(scissor) => {
|
||||||
let new_rect = rect.intersection(&scissor);
|
let new_rect = rect.intersection(&scissor);
|
||||||
match new_rect {
|
match new_rect {
|
||||||
|
@ -323,12 +331,16 @@ impl CompositorLayer {
|
||||||
match self.children.iter().position(|x| pipeline_id == x.child.pipeline.id) {
|
match self.children.iter().position(|x| pipeline_id == x.child.pipeline.id) {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
let child_node = &mut self.children[i];
|
let child_node = &mut self.children[i];
|
||||||
let con = child_node.container;
|
child_node.container.borrow().common.with_mut(|common|
|
||||||
con.common.set_transform(identity().translate(new_rect.origin.x,
|
common.set_transform(identity().translate(new_rect.origin.x,
|
||||||
new_rect.origin.y,
|
new_rect.origin.y,
|
||||||
0.0));
|
0.0)));
|
||||||
let old_rect = con.scissor;
|
let old_rect = {
|
||||||
con.scissor = Some(new_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 {
|
match self.quadtree {
|
||||||
NoTree(..) => {} // Nothing to do
|
NoTree(..) => {} // Nothing to do
|
||||||
Tree(ref mut quadtree) => {
|
Tree(ref mut quadtree) => {
|
||||||
|
@ -408,9 +420,10 @@ impl CompositorLayer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.root_layer.common.set_transform(identity().translate(self.scroll_offset.x,
|
self.root_layer.borrow().common.with_mut(|common|
|
||||||
self.scroll_offset.y,
|
common.set_transform(identity().translate(self.scroll_offset.x,
|
||||||
0.0));
|
self.scroll_offset.y,
|
||||||
|
0.0)));
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
FixedPosition => false // Ignore this scroll event.
|
FixedPosition => false // Ignore this scroll event.
|
||||||
|
@ -465,7 +478,9 @@ impl CompositorLayer {
|
||||||
max_mem))
|
max_mem))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match child_node.container.scissor {
|
// NOTE: work around borrowchk
|
||||||
|
let tmp = child_node.container.borrow().scissor.borrow();
|
||||||
|
match *tmp.get() {
|
||||||
Some(scissor) => {
|
Some(scissor) => {
|
||||||
// Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the cursor position
|
// 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.
|
// to make sure the scroll isn't propagated downwards.
|
||||||
|
@ -492,15 +507,21 @@ impl CompositorLayer {
|
||||||
// are not rebuilt directly from this method.
|
// are not rebuilt directly from this method.
|
||||||
pub fn build_layer_tree(&mut self, graphics_context: &NativeCompositingGraphicsContext) {
|
pub fn build_layer_tree(&mut self, graphics_context: &NativeCompositingGraphicsContext) {
|
||||||
// Iterate over the children of the container layer.
|
// 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.
|
// Delete old layer.
|
||||||
while current_layer_child.is_some() {
|
while current_layer_child.is_some() {
|
||||||
let trash = current_layer_child.unwrap();
|
let trash = current_layer_child.clone().unwrap();
|
||||||
current_layer_child.unwrap().with_common(|common| {
|
current_layer_child.clone().unwrap().with_common(|common| {
|
||||||
current_layer_child = common.next_sibling;
|
current_layer_child = common.next_sibling.clone();
|
||||||
});
|
});
|
||||||
self.root_layer.remove_child(trash);
|
ContainerLayer::remove_child(self.root_layer.clone(), trash);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new tiles.
|
// Add new tiles.
|
||||||
|
@ -519,7 +540,7 @@ impl CompositorLayer {
|
||||||
|
|
||||||
// Find or create a texture layer.
|
// Find or create a texture layer.
|
||||||
let texture_layer;
|
let texture_layer;
|
||||||
current_layer_child = match current_layer_child {
|
current_layer_child = match current_layer_child.clone() {
|
||||||
None => {
|
None => {
|
||||||
debug!("osmain: adding new texture layer");
|
debug!("osmain: adding new texture layer");
|
||||||
|
|
||||||
|
@ -536,19 +557,20 @@ impl CompositorLayer {
|
||||||
buffer.native_surface.bind_to_texture(graphics_context, &texture, size);
|
buffer.native_surface.bind_to_texture(graphics_context, &texture, size);
|
||||||
|
|
||||||
// Make a texture layer and add it.
|
// Make a texture layer and add it.
|
||||||
texture_layer = @mut TextureLayer::new(texture, buffer.screen_pos.size, flip);
|
texture_layer = Rc::new(TextureLayer::new(texture, buffer.screen_pos.size, flip));
|
||||||
self.root_layer.add_child_end(TextureLayerKind(texture_layer));
|
ContainerLayer::add_child_end(self.root_layer.clone(),
|
||||||
|
TextureLayerKind(texture_layer.clone()));
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Some(TextureLayerKind(existing_texture_layer)) => {
|
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);
|
buffer.native_surface.bind_to_texture(graphics_context, texture, size);
|
||||||
|
|
||||||
// Move on to the next sibling.
|
// Move on to the next sibling.
|
||||||
current_layer_child.unwrap().with_common(|common| {
|
current_layer_child.unwrap().with_common(|common| {
|
||||||
common.next_sibling
|
common.next_sibling.clone()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Some(_) => fail!(~"found unexpected layer kind"),
|
Some(_) => fail!(~"found unexpected layer kind"),
|
||||||
|
@ -558,17 +580,20 @@ impl CompositorLayer {
|
||||||
let rect = buffer.rect;
|
let rect = buffer.rect;
|
||||||
let transform = identity().translate(rect.origin.x, rect.origin.y, 0.0);
|
let transform = identity().translate(rect.origin.x, rect.origin.y, 0.0);
|
||||||
let transform = transform.scale(rect.size.width, rect.size.height, 1.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.
|
// Add child layers.
|
||||||
for child in self.children.mut_iter().filter(|x| !x.child.hidden) {
|
for child in self.children.mut_iter().filter(|x| !x.child.hidden) {
|
||||||
current_layer_child = match current_layer_child {
|
current_layer_child = match current_layer_child {
|
||||||
None => {
|
None => {
|
||||||
child.container.common.parent = None;
|
child.container.borrow().common.with_mut(|common| {
|
||||||
child.container.common.prev_sibling = None;
|
common.parent = None;
|
||||||
child.container.common.next_sibling = None;
|
common.prev_sibling = None;
|
||||||
self.root_layer.add_child_end(ContainerLayerKind(child.container));
|
common.next_sibling = None;
|
||||||
|
});
|
||||||
|
ContainerLayer::add_child_end(self.root_layer.clone(),
|
||||||
|
ContainerLayerKind(child.container.clone()));
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
|
@ -648,7 +673,9 @@ impl CompositorLayer {
|
||||||
match self.quadtree {
|
match self.quadtree {
|
||||||
NoTree(..) => {} // Nothing to do
|
NoTree(..) => {} // Nothing to do
|
||||||
Tree(ref mut quadtree) => {
|
Tree(ref mut quadtree) => {
|
||||||
match child.container.scissor {
|
// NOTE: work around borrowchk
|
||||||
|
let tmp = child.container.borrow().scissor.borrow();
|
||||||
|
match *tmp.get() {
|
||||||
Some(rect) => {
|
Some(rect) => {
|
||||||
quadtree.set_status_page(rect, Normal, false); // Unhide this rect
|
quadtree.set_status_page(rect, Normal, false); // Unhide this rect
|
||||||
}
|
}
|
||||||
|
@ -692,7 +719,9 @@ impl CompositorLayer {
|
||||||
Tree(ref mut quadtree) => quadtree,
|
Tree(ref mut quadtree) => quadtree,
|
||||||
};
|
};
|
||||||
for child in self.children.iter().filter(|x| !x.child.hidden) {
|
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
|
None => {} // Nothing to do
|
||||||
Some(rect) => {
|
Some(rect) => {
|
||||||
quadtree.set_status_page(rect, Hidden, false);
|
quadtree.set_status_page(rect, Hidden, false);
|
||||||
|
|
|
@ -24,8 +24,11 @@ use servo_net::resource_task;
|
||||||
use servo_util::time::ProfilerChan;
|
use servo_util::time::ProfilerChan;
|
||||||
use servo_util::url::parse_url;
|
use servo_util::url::parse_url;
|
||||||
use servo_util::task::spawn_named;
|
use servo_util::task::spawn_named;
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::hashmap::{HashMap, HashSet};
|
use std::hashmap::{HashMap, HashSet};
|
||||||
use std::rc::Rc;
|
//FIXME: switch to std::rc when we upgrade Rust
|
||||||
|
use layers::temp_rc::Rc;
|
||||||
|
//use std::rc::Rc;
|
||||||
use std::util::replace;
|
use std::util::replace;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::libc;
|
use std::libc;
|
||||||
|
@ -49,27 +52,28 @@ pub struct Constellation {
|
||||||
|
|
||||||
/// Stores the Id of the outermost frame's pipeline, along with a vector of children frames
|
/// Stores the Id of the outermost frame's pipeline, along with a vector of children frames
|
||||||
struct FrameTree {
|
struct FrameTree {
|
||||||
pipeline: Rc<Pipeline>,
|
pipeline: RefCell<Rc<Pipeline>>,
|
||||||
parent: Option<Rc<Pipeline>>,
|
parent: RefCell<Option<Rc<Pipeline>>>,
|
||||||
children: ~[ChildFrameTree],
|
children: RefCell<~[ChildFrameTree]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to clone the FrameTrees, but _not_ the Pipelines
|
// Need to clone the FrameTrees, but _not_ the Pipelines
|
||||||
impl Clone for FrameTree {
|
impl Clone for FrameTree {
|
||||||
fn clone(&self) -> 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()
|
child_frame_tree.clone()
|
||||||
});
|
});
|
||||||
FrameTree {
|
FrameTree {
|
||||||
pipeline: self.pipeline.clone(),
|
pipeline: self.pipeline.clone(),
|
||||||
parent: self.parent.clone(),
|
parent: self.parent.clone(),
|
||||||
children: children.collect(),
|
children: RefCell::new(children.collect()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChildFrameTree {
|
struct ChildFrameTree {
|
||||||
frame_tree: @mut FrameTree,
|
frame_tree: Rc<FrameTree>,
|
||||||
/// Clipping rect representing the size and position, in page coordinates, of the visible
|
/// Clipping rect representing the size and position, in page coordinates, of the visible
|
||||||
/// region of the child frame relative to the parent.
|
/// region of the child frame relative to the parent.
|
||||||
rect: Option<Rect<f32>>,
|
rect: Option<Rect<f32>>,
|
||||||
|
@ -78,7 +82,7 @@ struct ChildFrameTree {
|
||||||
impl Clone for ChildFrameTree {
|
impl Clone for ChildFrameTree {
|
||||||
fn clone(&self) -> ChildFrameTree {
|
fn clone(&self) -> ChildFrameTree {
|
||||||
ChildFrameTree {
|
ChildFrameTree {
|
||||||
frame_tree: @mut (*self.frame_tree).clone(),
|
frame_tree: self.frame_tree.clone(),
|
||||||
rect: self.rect.clone(),
|
rect: self.rect.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,32 +108,46 @@ pub struct SendableChildFrameTree {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
enum ReplaceResult {
|
enum ReplaceResult {
|
||||||
ReplacedNode(@mut FrameTree),
|
ReplacedNode(Rc<FrameTree>),
|
||||||
OriginalNode(@mut FrameTree),
|
OriginalNode(Rc<FrameTree>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FrameTree {
|
impl FrameTree {
|
||||||
fn contains(@mut self, id: PipelineId) -> bool {
|
fn contains(&self, id: PipelineId) -> bool {
|
||||||
self.iter().any(|frame_tree| {
|
self.iter().any(|frame_tree| {
|
||||||
id == frame_tree.pipeline.borrow().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
|
/// 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| {
|
self.iter().find(|frame_tree| {
|
||||||
id == frame_tree.pipeline.borrow().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
|
/// 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.
|
/// 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() {
|
for frame_tree in self.iter() {
|
||||||
let mut child = frame_tree.children.mut_iter()
|
// NOTE: work around mutability issue
|
||||||
.find(|child| child.frame_tree.pipeline.borrow().id == id);
|
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() {
|
for child in child.mut_iter() {
|
||||||
new_child.parent = child.frame_tree.parent.clone();
|
// 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));
|
return ReplacedNode(replace(&mut child.frame_tree, new_child));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,15 +156,23 @@ impl FrameTree {
|
||||||
|
|
||||||
fn to_sendable(&self) -> SendableFrameTree {
|
fn to_sendable(&self) -> SendableFrameTree {
|
||||||
let sendable_frame_tree = SendableFrameTree {
|
let sendable_frame_tree = SendableFrameTree {
|
||||||
pipeline: self.pipeline.borrow().to_sendable(),
|
pipeline: {
|
||||||
children: self.children.iter().map(|frame_tree| frame_tree.to_sendable()).collect(),
|
// 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
|
sendable_frame_tree
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(@mut self) -> FrameTreeIterator {
|
pub fn iter(&self) -> FrameTreeIterator {
|
||||||
FrameTreeIterator {
|
FrameTreeIterator {
|
||||||
stack: ~[self],
|
stack: ~[Rc::new(self.clone())],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,7 +180,7 @@ impl FrameTree {
|
||||||
impl ChildFrameTree {
|
impl ChildFrameTree {
|
||||||
fn to_sendable(&self) -> SendableChildFrameTree {
|
fn to_sendable(&self) -> SendableChildFrameTree {
|
||||||
SendableChildFrameTree {
|
SendableChildFrameTree {
|
||||||
frame_tree: self.frame_tree.to_sendable(),
|
frame_tree: self.frame_tree.borrow().to_sendable(),
|
||||||
rect: self.rect,
|
rect: self.rect,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,15 +190,19 @@ impl ChildFrameTree {
|
||||||
/// Note that this iterator should _not_ be used to mutate nodes _during_
|
/// Note that this iterator should _not_ be used to mutate nodes _during_
|
||||||
/// iteration. Mutating nodes once the iterator is out of scope is OK.
|
/// iteration. Mutating nodes once the iterator is out of scope is OK.
|
||||||
pub struct FrameTreeIterator {
|
pub struct FrameTreeIterator {
|
||||||
priv stack: ~[@mut FrameTree],
|
priv stack: ~[Rc<FrameTree>],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator<@mut FrameTree> for FrameTreeIterator {
|
impl Iterator<Rc<FrameTree>> for FrameTreeIterator {
|
||||||
fn next(&mut self) -> Option<@mut FrameTree> {
|
fn next(&mut self) -> Option<Rc<FrameTree>> {
|
||||||
if !self.stack.is_empty() {
|
if !self.stack.is_empty() {
|
||||||
let next = self.stack.pop();
|
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)
|
Some(next)
|
||||||
} else {
|
} else {
|
||||||
|
@ -184,15 +214,15 @@ impl Iterator<@mut FrameTree> for FrameTreeIterator {
|
||||||
/// Represents the portion of a page that is changing in navigating.
|
/// Represents the portion of a page that is changing in navigating.
|
||||||
struct FrameChange {
|
struct FrameChange {
|
||||||
before: Option<PipelineId>,
|
before: Option<PipelineId>,
|
||||||
after: @mut FrameTree,
|
after: Rc<FrameTree>,
|
||||||
navigation_type: NavigationType,
|
navigation_type: NavigationType,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores the Id's of the pipelines previous and next in the browser's history
|
/// Stores the Id's of the pipelines previous and next in the browser's history
|
||||||
struct NavigationContext {
|
struct NavigationContext {
|
||||||
previous: ~[@mut FrameTree],
|
previous: ~[Rc<FrameTree>],
|
||||||
next: ~[@mut FrameTree],
|
next: ~[Rc<FrameTree>],
|
||||||
current: Option<@mut FrameTree>,
|
current: Option<Rc<FrameTree>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NavigationContext {
|
impl NavigationContext {
|
||||||
|
@ -207,39 +237,45 @@ impl NavigationContext {
|
||||||
/* Note that the following two methods can fail. They should only be called *
|
/* 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. */
|
* 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.next.push(self.current.take_unwrap());
|
||||||
self.current = Some(self.previous.pop());
|
let prev = self.previous.pop();
|
||||||
self.current.unwrap()
|
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.previous.push(self.current.take_unwrap());
|
||||||
self.current = Some(self.next.pop());
|
let next = self.next.pop();
|
||||||
self.current.unwrap()
|
self.current = Some(next.clone());
|
||||||
|
next
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a new set of page frames, returning all evicted frame trees
|
/// Loads a new set of page frames, returning all evicted frame trees
|
||||||
pub fn load(&mut self, frame_tree: @mut FrameTree) -> ~[@mut FrameTree] {
|
pub fn load(&mut self, frame_tree: Rc<FrameTree>) -> ~[Rc<FrameTree>] {
|
||||||
debug!("navigating to {:?}", frame_tree.pipeline.borrow().id);
|
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, ~[]);
|
let evicted = replace(&mut self.next, ~[]);
|
||||||
if self.current.is_some() {
|
if self.current.is_some() {
|
||||||
self.previous.push(self.current.take_unwrap());
|
self.previous.push(self.current.take_unwrap());
|
||||||
}
|
}
|
||||||
self.current = Some(frame_tree);
|
self.current = Some(frame_tree.clone());
|
||||||
evicted
|
evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the frame trees whose keys are pipeline_id.
|
/// 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| {
|
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| {
|
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| {
|
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()
|
from_prev.chain(from_current).chain(from_next).collect()
|
||||||
}
|
}
|
||||||
|
@ -251,7 +287,7 @@ impl NavigationContext {
|
||||||
|
|
||||||
let mut all_contained = from_prev.chain(from_current).chain(from_next);
|
let mut all_contained = from_prev.chain(from_current).chain(from_next);
|
||||||
all_contained.any(|frame_tree| {
|
all_contained.any(|frame_tree| {
|
||||||
frame_tree.contains(pipeline_id)
|
frame_tree.borrow().contains(pipeline_id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,18 +338,18 @@ impl Constellation {
|
||||||
*self.next_pipeline_id += 1;
|
*self.next_pipeline_id += 1;
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function for getting the currently active frame tree.
|
/// Convenience function for getting the currently active frame tree.
|
||||||
/// The currently active frame tree should always be the current painter
|
/// 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
|
&self.navigation_context.current
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns both the navigation context and pending frame trees whose keys are pipeline_id.
|
/// 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_navi_frames = self.navigation_context.find_all(pipeline_id);
|
||||||
let matching_pending_frames = self.pending_frames.iter().filter_map(|frame_change| {
|
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()
|
matching_navi_frames.move_iter().chain(matching_pending_frames).collect()
|
||||||
}
|
}
|
||||||
|
@ -398,12 +434,12 @@ impl Constellation {
|
||||||
|
|
||||||
let old_pipeline = match self.pipelines.find(&pipeline_id) {
|
let old_pipeline = match self.pipelines.find(&pipeline_id) {
|
||||||
None => return, // already failed?
|
None => return, // already failed?
|
||||||
Some(id) => *id
|
Some(id) => id.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
old_pipeline.script_chan.try_send(ExitPipelineMsg(pipeline_id));
|
old_pipeline.borrow().script_chan.try_send(ExitPipelineMsg(pipeline_id));
|
||||||
old_pipeline.render_chan.try_send(render_task::ExitMsg(None));
|
old_pipeline.borrow().render_chan.try_send(render_task::ExitMsg(None));
|
||||||
old_pipeline.layout_chan.try_send(layout_interface::ExitNowMsg);
|
old_pipeline.borrow().layout_chan.try_send(layout_interface::ExitNowMsg);
|
||||||
self.pipelines.remove(&pipeline_id);
|
self.pipelines.remove(&pipeline_id);
|
||||||
|
|
||||||
let new_id = self.get_next_pipeline_id();
|
let new_id = self.get_next_pipeline_id();
|
||||||
|
@ -419,17 +455,17 @@ impl Constellation {
|
||||||
let url = parse_url("about:failure", None);
|
let url = parse_url("about:failure", None);
|
||||||
pipeline.load(url);
|
pipeline.load(url);
|
||||||
|
|
||||||
let pipeline_wrapped = Rc::from_send(pipeline);
|
let pipeline_wrapped = Rc::new(pipeline);
|
||||||
self.pending_frames.push(FrameChange{
|
self.pending_frames.push(FrameChange{
|
||||||
before: Some(pipeline_id),
|
before: Some(pipeline_id),
|
||||||
after: Rc::from_send(FrameTree {
|
after: Rc::new(FrameTree {
|
||||||
pipeline: pipeline_wrapped.clone(),
|
pipeline: RefCell::new(pipeline_wrapped.clone()),
|
||||||
parent: None,
|
parent: RefCell::new(None),
|
||||||
children: ~[],
|
children: RefCell::new(~[]),
|
||||||
}),
|
}),
|
||||||
navigation_type: constellation_msg::Navigate,
|
navigation_type: constellation_msg::Navigate,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.pipelines.insert(pipeline_id, pipeline_wrapped);
|
self.pipelines.insert(pipeline_id, pipeline_wrapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,27 +480,30 @@ impl Constellation {
|
||||||
self.window_size,
|
self.window_size,
|
||||||
self.opts.clone());
|
self.opts.clone());
|
||||||
pipeline.load(url);
|
pipeline.load(url);
|
||||||
let pipeline_wrapped = Rc::from_send(pipeline);
|
let pipeline_wrapped = Rc::new(pipeline);
|
||||||
|
|
||||||
self.pending_frames.push(FrameChange {
|
self.pending_frames.push(FrameChange {
|
||||||
before: None,
|
before: None,
|
||||||
after: @mut FrameTree {
|
after: Rc::new(FrameTree {
|
||||||
pipeline: pipeline_wrapped.clone(),
|
pipeline: RefCell::new(pipeline_wrapped.clone()),
|
||||||
parent: None,
|
parent: RefCell::new(None),
|
||||||
children: ~[],
|
children: RefCell::new(~[]),
|
||||||
},
|
}),
|
||||||
navigation_type: constellation_msg::Load,
|
navigation_type: constellation_msg::Load,
|
||||||
});
|
});
|
||||||
self.pipelines.insert(pipeline_wrapped.borrow().id, pipeline_wrapped);
|
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>) {
|
fn handle_frame_rect_msg(&mut self, pipeline_id: PipelineId, subpage_id: SubpageId, rect: Rect<f32>) {
|
||||||
debug!("Received frame rect {} from {:?}, {:?}", rect, pipeline_id, subpage_id);
|
debug!("Received frame rect {} from {:?}, {:?}", rect, pipeline_id, subpage_id);
|
||||||
let mut already_sent = HashSet::new();
|
let mut already_sent = HashSet::new();
|
||||||
|
|
||||||
// Returns true if a child frame tree's subpage id matches the given subpage id
|
// Returns true if a child frame tree's subpage id matches the given subpage id
|
||||||
let subpage_eq = |child_frame_tree: & &mut ChildFrameTree| {
|
let subpage_eq = |child_frame_tree: & &mut ChildFrameTree| {
|
||||||
child_frame_tree.frame_tree.pipeline.borrow().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.")
|
child frame does not have a subpage id. This should not be possible.")
|
||||||
== subpage_id
|
== subpage_id
|
||||||
};
|
};
|
||||||
|
@ -474,22 +513,23 @@ impl Constellation {
|
||||||
// resize happens immediately.
|
// resize happens immediately.
|
||||||
let update_child_rect = |child_frame_tree: &mut ChildFrameTree, is_active: bool| {
|
let update_child_rect = |child_frame_tree: &mut ChildFrameTree, is_active: bool| {
|
||||||
child_frame_tree.rect = Some(rect.clone());
|
child_frame_tree.rect = Some(rect.clone());
|
||||||
let pipeline = &child_frame_tree.frame_tree.pipeline;
|
// NOTE: work around borrowchk issues
|
||||||
if !already_sent.contains(&pipeline.borrow().id) {
|
let pipeline = &child_frame_tree.frame_tree.borrow().pipeline.borrow();
|
||||||
|
if !already_sent.contains(&pipeline.get().borrow().id) {
|
||||||
let Size2D { width, height } = rect.size;
|
let Size2D { width, height } = rect.size;
|
||||||
if is_active {
|
if is_active {
|
||||||
let pipeline = pipeline.borrow();
|
let pipeline = pipeline.get().borrow();
|
||||||
pipeline.script_chan.send(ResizeMsg(pipeline.id, Size2D {
|
pipeline.script_chan.send(ResizeMsg(pipeline.id, Size2D {
|
||||||
width: width as uint,
|
width: width as uint,
|
||||||
height: height as uint
|
height: height as uint
|
||||||
}));
|
}));
|
||||||
self.compositor_chan.send(SetLayerClipRect(pipeline.id, rect));
|
self.compositor_chan.send(SetLayerClipRect(pipeline.id, rect));
|
||||||
} else {
|
} else {
|
||||||
let pipeline = pipeline.borrow();
|
let pipeline = pipeline.get().borrow();
|
||||||
pipeline.script_chan.send(ResizeInactiveMsg(pipeline.id,
|
pipeline.script_chan.send(ResizeInactiveMsg(pipeline.id,
|
||||||
Size2D(width as uint, height as uint)));
|
Size2D(width as uint, height as uint)));
|
||||||
}
|
}
|
||||||
let pipeline = pipeline.borrow();
|
let pipeline = pipeline.get().borrow();
|
||||||
already_sent.insert(pipeline.id);
|
already_sent.insert(pipeline.id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -497,10 +537,11 @@ impl Constellation {
|
||||||
// If the subframe is in the current frame tree, the compositor needs the new size
|
// If the subframe is in the current frame tree, the compositor needs the new size
|
||||||
for current_frame in self.current_frame().iter() {
|
for current_frame in self.current_frame().iter() {
|
||||||
debug!("Constellation: Sending size for frame in current frame tree.");
|
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() {
|
for source_frame in source_frame.iter() {
|
||||||
let found_child = source_frame.children.mut_iter()
|
// NOTE: work around borrowchk issues
|
||||||
.find(|child| subpage_eq(child));
|
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));
|
found_child.map(|child| update_child_rect(child, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -508,8 +549,9 @@ impl Constellation {
|
||||||
// Update all frames with matching pipeline- and subpage-ids
|
// Update all frames with matching pipeline- and subpage-ids
|
||||||
let frames = self.find_all(pipeline_id);
|
let frames = self.find_all(pipeline_id);
|
||||||
for frame_tree in frames.iter() {
|
for frame_tree in frames.iter() {
|
||||||
let found_child = frame_tree.children.mut_iter()
|
// NOTE: work around borrowchk issues
|
||||||
.find(|child| subpage_eq(child));
|
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));
|
found_child.map(|child| update_child_rect(child, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,10 +574,10 @@ impl Constellation {
|
||||||
// or a new url entered.
|
// or a new url entered.
|
||||||
// Start by finding the frame trees matching the pipeline id,
|
// Start by finding the frame trees matching the pipeline id,
|
||||||
// and add the new pipeline to their sub frames.
|
// 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_navi_frames = self.navigation_context.find_all(source_pipeline_id);
|
||||||
let matching_pending_frames = self.pending_frames.iter().filter_map(|frame_change| {
|
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()
|
matching_navi_frames.move_iter().chain(matching_pending_frames).collect()
|
||||||
};
|
};
|
||||||
|
@ -588,15 +630,17 @@ impl Constellation {
|
||||||
|
|
||||||
debug!("Constellation: sending load msg to pipeline {:?}", pipeline.id);
|
debug!("Constellation: sending load msg to pipeline {:?}", pipeline.id);
|
||||||
pipeline.load(url);
|
pipeline.load(url);
|
||||||
let pipeline_wrapped = Rc::from_send(pipeline);
|
let pipeline_wrapped = Rc::new(pipeline);
|
||||||
let rect = self.pending_sizes.pop(&(source_pipeline_id, subpage_id));
|
let rect = self.pending_sizes.pop(&(source_pipeline_id, subpage_id));
|
||||||
for frame_tree in frame_trees.iter() {
|
for frame_tree in frame_trees.iter() {
|
||||||
frame_tree.children.push(ChildFrameTree {
|
// NOTE: work around borrowchk issues
|
||||||
frame_tree: @mut FrameTree {
|
let mut tmp = frame_tree.borrow().children.borrow_mut();
|
||||||
pipeline: pipeline_wrapped.clone(),
|
tmp.get().push(ChildFrameTree {
|
||||||
parent: Some(source_pipeline.clone()),
|
frame_tree: Rc::new(FrameTree {
|
||||||
children: ~[],
|
pipeline: RefCell::new(pipeline_wrapped.clone()),
|
||||||
},
|
parent: RefCell::new(Some(source_pipeline.clone())),
|
||||||
|
children: RefCell::new(~[]),
|
||||||
|
}),
|
||||||
rect: rect,
|
rect: rect,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -606,7 +650,7 @@ impl Constellation {
|
||||||
fn handle_load_url_msg(&mut self, source_id: PipelineId, url: Url) {
|
fn handle_load_url_msg(&mut self, source_id: PipelineId, url: Url) {
|
||||||
debug!("Constellation: received message to load {:s}", url.to_str());
|
debug!("Constellation: received message to load {:s}", url.to_str());
|
||||||
// Make sure no pending page would be overridden.
|
// 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
|
"Constellation: received a LoadUrlMsg from a pipeline_id associated
|
||||||
with a pipeline not in the active frame tree. This should be
|
with a pipeline not in the active frame tree. This should be
|
||||||
impossible.");
|
impossible.");
|
||||||
|
@ -615,10 +659,10 @@ impl Constellation {
|
||||||
let old_id = frame_change.before.expect("Constellation: Received load msg
|
let old_id = frame_change.before.expect("Constellation: Received load msg
|
||||||
from pipeline, but there is no currently active page. This should
|
from pipeline, but there is no currently active page. This should
|
||||||
be impossible.");
|
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
|
Pending change has non-active source pipeline. This should be
|
||||||
impossible.");
|
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
|
// id that sent load msg is being changed already; abort
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -626,8 +670,10 @@ impl Constellation {
|
||||||
// Being here means either there are no pending frames, or none of the pending
|
// 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.
|
// changes would be overriden by changing the subframe associated with source_id.
|
||||||
|
|
||||||
let parent = source_frame.parent.clone();
|
let parent = source_frame.borrow().parent.clone();
|
||||||
let subpage_id = source_frame.pipeline.borrow().subpage_id;
|
// 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 next_pipeline_id = self.get_next_pipeline_id();
|
||||||
|
|
||||||
let pipeline = Pipeline::create(next_pipeline_id,
|
let pipeline = Pipeline::create(next_pipeline_id,
|
||||||
|
@ -641,20 +687,20 @@ impl Constellation {
|
||||||
self.opts.clone());
|
self.opts.clone());
|
||||||
|
|
||||||
pipeline.load(url);
|
pipeline.load(url);
|
||||||
let pipeline_wrapped = Rc::from_send(pipeline);
|
let pipeline_wrapped = Rc::new(pipeline);
|
||||||
|
|
||||||
self.pending_frames.push(FrameChange{
|
self.pending_frames.push(FrameChange{
|
||||||
before: Some(source_id),
|
before: Some(source_id),
|
||||||
after: @mut FrameTree {
|
after: Rc::new(FrameTree {
|
||||||
pipeline: pipeline_wrapped.clone(),
|
pipeline: RefCell::new(pipeline_wrapped.clone()),
|
||||||
parent: parent,
|
parent: parent,
|
||||||
children: ~[],
|
children: RefCell::new(~[]),
|
||||||
},
|
}),
|
||||||
navigation_type: constellation_msg::Load,
|
navigation_type: constellation_msg::Load,
|
||||||
});
|
});
|
||||||
self.pipelines.insert(pipeline_wrapped.borrow().id, pipeline_wrapped);
|
self.pipelines.insert(pipeline_wrapped.borrow().id, pipeline_wrapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_navigate_msg(&mut self, direction: constellation_msg::NavigationDirection) {
|
fn handle_navigate_msg(&mut self, direction: constellation_msg::NavigationDirection) {
|
||||||
debug!("received message to navigate {:?}", direction);
|
debug!("received message to navigate {:?}", direction);
|
||||||
|
|
||||||
|
@ -669,8 +715,10 @@ impl Constellation {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
let old = self.current_frame().get_ref();
|
let old = self.current_frame().get_ref();
|
||||||
for frame in old.iter() {
|
for frame in old.borrow().iter() {
|
||||||
frame.pipeline.borrow().revoke_paint_permission();
|
// NOTE: work around borrowchk issues
|
||||||
|
let tmp = frame.borrow().pipeline.borrow();
|
||||||
|
tmp.get().borrow().revoke_paint_permission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.navigation_context.forward()
|
self.navigation_context.forward()
|
||||||
|
@ -681,35 +729,40 @@ impl Constellation {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
let old = self.current_frame().get_ref();
|
let old = self.current_frame().get_ref();
|
||||||
for frame in old.iter() {
|
for frame in old.borrow().iter() {
|
||||||
frame.pipeline.borrow().revoke_paint_permission();
|
// NOTE: work around borrowchk issues
|
||||||
|
let tmp = frame.borrow().pipeline.borrow();
|
||||||
|
tmp.get().borrow().revoke_paint_permission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.navigation_context.back()
|
self.navigation_context.back()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for frame in destination_frame.iter() {
|
for frame in destination_frame.borrow().iter() {
|
||||||
let pipeline = &frame.pipeline;
|
// NOTE: work around borrowchk issues
|
||||||
pipeline.borrow().reload();
|
let pipeline = &frame.borrow().pipeline.borrow();
|
||||||
|
pipeline.get().borrow().reload();
|
||||||
}
|
}
|
||||||
self.grant_paint_permission(destination_frame, constellation_msg::Navigate);
|
self.grant_paint_permission(destination_frame, constellation_msg::Navigate);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_renderer_ready_msg(&mut self, pipeline_id: PipelineId) {
|
fn handle_renderer_ready_msg(&mut self, pipeline_id: PipelineId) {
|
||||||
debug!("Renderer {:?} ready to send paint msg", pipeline_id);
|
debug!("Renderer {:?} ready to send paint msg", pipeline_id);
|
||||||
// This message could originate from a pipeline in the navigation context or
|
// This message could originate from a pipeline in the navigation context or
|
||||||
// from a pending frame. The only time that we will grant paint permission is
|
// 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.
|
// 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;
|
// Messages originating in the current frame are not navigations;
|
||||||
// TODO(tkuehn): In fact, this kind of message might be provably
|
// TODO(tkuehn): In fact, this kind of message might be provably
|
||||||
// impossible to occur.
|
// impossible to occur.
|
||||||
if current_frame.contains(pipeline_id) {
|
if current_frame.borrow().contains(pipeline_id) {
|
||||||
for frame in current_frame.iter() {
|
for frame in current_frame.borrow().iter() {
|
||||||
frame.pipeline.borrow().grant_paint_permission();
|
// NOTE: work around borrowchk issues
|
||||||
|
let tmp = frame.borrow().pipeline.borrow();
|
||||||
|
tmp.get().borrow().grant_paint_permission();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -719,53 +772,87 @@ impl Constellation {
|
||||||
// If it is not found, it simply means that this pipeline will not receive
|
// If it is not found, it simply means that this pipeline will not receive
|
||||||
// permission to paint.
|
// permission to paint.
|
||||||
let pending_index = self.pending_frames.iter().rposition(|frame_change| {
|
let pending_index = self.pending_frames.iter().rposition(|frame_change| {
|
||||||
frame_change.after.pipeline.borrow().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() {
|
for &pending_index in pending_index.iter() {
|
||||||
let frame_change = self.pending_frames.swap_remove(pending_index);
|
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
|
// Create the next frame tree that will be given to the compositor
|
||||||
let next_frame_tree = match to_add.parent.clone() {
|
// NOTE: work around borrowchk issues
|
||||||
None => to_add, // to_add is the root
|
let tmp = to_add.borrow().parent.clone();
|
||||||
Some(_parent) => @mut (*self.current_frame().unwrap()).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.
|
// If there are frames to revoke permission from, do so now.
|
||||||
match frame_change.before {
|
match frame_change.before {
|
||||||
Some(revoke_id) => {
|
Some(revoke_id) => {
|
||||||
debug!("Constellation: revoking permission from {:?}", 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
|
"Constellation: pending frame change refers to an old
|
||||||
frame not contained in the current frame. This is a bug");
|
frame not contained in the current frame. This is a bug");
|
||||||
|
|
||||||
for frame in to_revoke.iter() {
|
for frame in to_revoke.borrow().iter() {
|
||||||
frame.pipeline.borrow().revoke_paint_permission();
|
// 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.
|
// If to_add is not the root frame, then replace revoked_frame with it.
|
||||||
// This conveniently keeps scissor rect size intact.
|
// This conveniently keeps scissor rect size intact.
|
||||||
if to_add.parent.is_some() {
|
// NOTE: work around borrowchk issue
|
||||||
debug!("Constellation: replacing {:?} with {:?} in {:?}",
|
let mut flag = false;
|
||||||
revoke_id, to_add.pipeline.borrow().id, next_frame_tree.pipeline.borrow().id);
|
{
|
||||||
next_frame_tree.replace_child(revoke_id, to_add);
|
// 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 => {
|
None => {
|
||||||
// Add to_add to parent's children, if it is not the root
|
// Add to_add to parent's children, if it is not the root
|
||||||
let parent = &to_add.parent;
|
let parent = &to_add.borrow().parent;
|
||||||
for parent in parent.iter() {
|
// NOTE: work around borrowchk issue
|
||||||
let subpage_id = to_add.pipeline.borrow().subpage_id.expect("Constellation:
|
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.");
|
Child frame's subpage id is None. This should be impossible.");
|
||||||
let rect = self.pending_sizes.pop(&(parent.borrow().id, subpage_id));
|
let rect = self.pending_sizes.pop(&(parent.borrow().id, subpage_id));
|
||||||
let parent = next_frame_tree.find(parent.borrow().id).expect(
|
let parent = next_frame_tree.borrow().find(parent.borrow().id).expect(
|
||||||
"Constellation: pending frame has a parent frame that is not
|
"Constellation: pending frame has a parent frame that is not
|
||||||
active. This is a bug.");
|
active. This is a bug.");
|
||||||
parent.children.push(ChildFrameTree {
|
// NOTE: work around borrowchk issue
|
||||||
frame_tree: to_add,
|
let mut tmp = parent.borrow().children.borrow_mut();
|
||||||
|
tmp.get().push(ChildFrameTree {
|
||||||
|
frame_tree: to_add.clone(),
|
||||||
rect: rect,
|
rect: rect,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -781,16 +868,19 @@ impl Constellation {
|
||||||
let mut already_seen = HashSet::new();
|
let mut already_seen = HashSet::new();
|
||||||
for frame_tree in self.current_frame().iter() {
|
for frame_tree in self.current_frame().iter() {
|
||||||
debug!("constellation sending resize message to active frame");
|
debug!("constellation sending resize message to active frame");
|
||||||
let pipeline = frame_tree.pipeline.borrow();
|
// 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));
|
pipeline.script_chan.try_send(ResizeMsg(pipeline.id, new_size));
|
||||||
already_seen.insert(pipeline.id);
|
already_seen.insert(pipeline.id);
|
||||||
}
|
}
|
||||||
for frame_tree in self.navigation_context.previous.iter()
|
for frame_tree in self.navigation_context.previous.iter()
|
||||||
.chain(self.navigation_context.next.iter()) {
|
.chain(self.navigation_context.next.iter()) {
|
||||||
let pipeline = &frame_tree.pipeline;
|
// NOTE: work around borrowchk issues
|
||||||
if !already_seen.contains(&pipeline.borrow().id) {
|
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");
|
debug!("constellation sending resize message to inactive frame");
|
||||||
let pipeline = pipeline.borrow();
|
|
||||||
pipeline.script_chan.try_send(ResizeInactiveMsg(pipeline.id, new_size));
|
pipeline.script_chan.try_send(ResizeInactiveMsg(pipeline.id, new_size));
|
||||||
already_seen.insert(pipeline.id);
|
already_seen.insert(pipeline.id);
|
||||||
}
|
}
|
||||||
|
@ -799,10 +889,14 @@ impl Constellation {
|
||||||
// If there are any pending outermost frames, then tell them to resize. (This is how the
|
// 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.)
|
// initial window size gets sent to the first page loaded, giving it permission to reflow.)
|
||||||
for change in self.pending_frames.iter() {
|
for change in self.pending_frames.iter() {
|
||||||
let frame_tree = change.after;
|
let frame_tree = change.after.borrow();
|
||||||
if frame_tree.parent.is_none() {
|
// 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");
|
debug!("constellation sending resize message to pending outer frame");
|
||||||
let pipeline = frame_tree.pipeline.borrow();
|
// 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))
|
pipeline.script_chan.send(ResizeMsg(pipeline.id, new_size))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -811,32 +905,38 @@ impl Constellation {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close all pipelines at and beneath a given frame
|
// 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,
|
// TODO(tkuehn): should only exit once per unique script task,
|
||||||
// and then that script task will handle sub-exits
|
// and then that script task will handle sub-exits
|
||||||
for frame_tree in frame_tree.iter() {
|
for frame_tree in frame_tree.borrow().iter() {
|
||||||
let pipeline = frame_tree.pipeline.borrow();
|
// NOTE: work around borrowchk issues
|
||||||
|
let tmp = frame_tree.borrow().pipeline.borrow();
|
||||||
|
let pipeline = tmp.get().borrow();
|
||||||
pipeline.exit();
|
pipeline.exit();
|
||||||
self.pipelines.remove(&pipeline.id);
|
self.pipelines.remove(&pipeline.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_evicted_frames(&mut self, evicted: ~[@mut FrameTree]) {
|
fn handle_evicted_frames(&mut self, evicted: ~[Rc<FrameTree>]) {
|
||||||
for &frame_tree in evicted.iter() {
|
for frame_tree in evicted.iter() {
|
||||||
if !self.navigation_context.contains(frame_tree.pipeline.borrow().id) {
|
// NOTE: work around borrowchk issues
|
||||||
self.close_pipelines(frame_tree);
|
let tmp = frame_tree.borrow().pipeline.borrow();
|
||||||
|
if !self.navigation_context.contains(tmp.get().borrow().id) {
|
||||||
|
self.close_pipelines(frame_tree.clone());
|
||||||
} else {
|
} else {
|
||||||
self.handle_evicted_frames(frame_tree.children.iter()
|
// NOTE: work around borrowchk issue
|
||||||
.map(|child| child.frame_tree)
|
let tmp = frame_tree.borrow().children.borrow();
|
||||||
.collect());
|
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
|
// 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
|
// 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
|
// Don't call navigation_context.load() on a Navigate type (or None, as in the case of
|
||||||
// parsed iframes that finish loading)
|
// parsed iframes that finish loading)
|
||||||
|
@ -849,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();
|
let (port, chan) = Chan::new();
|
||||||
debug!("Constellation sending SetIds");
|
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() {
|
match port.recv_opt() {
|
||||||
Some(()) => {
|
Some(()) => {
|
||||||
for frame in frame_tree.iter() {
|
let mut iter = frame_tree.borrow().iter();
|
||||||
frame.pipeline.borrow().grant_paint_permission();
|
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
|
None => {} // message has been discarded, probably shutting down
|
||||||
|
|
|
@ -20,7 +20,9 @@ use servo_net::image_cache_task::ImageCacheTask;
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
use servo_util::time::ProfilerChan;
|
use servo_util::time::ProfilerChan;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
//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.
|
/// A uniquely-identifiable pipeline of script task, layout task, and render task.
|
||||||
pub struct Pipeline {
|
pub struct Pipeline {
|
||||||
|
|
|
@ -27,4 +27,3 @@ pub mod time;
|
||||||
pub mod url;
|
pub mod url;
|
||||||
pub mod vec;
|
pub mod vec;
|
||||||
pub mod workqueue;
|
pub mod workqueue;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue