mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
reorganized constellation.
compositor routes dom events via constellation. constellation handles iframe sizing and resizing.
This commit is contained in:
parent
e4d44fb8d2
commit
86f0aacb3d
5 changed files with 445 additions and 348 deletions
|
@ -136,7 +136,7 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
|||
match self.port.recv() {
|
||||
RenderMsg(render_layer) => {
|
||||
if self.paint_permission {
|
||||
self.compositor.new_layer(self.id, render_layer.size);
|
||||
self.compositor.resize_layer(self.id, render_layer.size);
|
||||
}
|
||||
self.render_layer = Some(render_layer);
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
|||
self.paint_permission = true;
|
||||
match self.render_layer {
|
||||
Some(ref render_layer) => {
|
||||
self.compositor.new_layer(self.id, render_layer.size);
|
||||
self.compositor.resize_layer(self.id, render_layer.size);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use platform::{Application, Window};
|
||||
use script::dom::event::ResizeEvent;
|
||||
use script::script_task::{LoadMsg, NavigateMsg, SendEventMsg};
|
||||
|
||||
pub use windowing;
|
||||
use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
|
||||
|
@ -14,7 +12,7 @@ use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEven
|
|||
|
||||
use servo_msg::compositor_msg::{RenderListener, LayerBufferSet, RenderState};
|
||||
use servo_msg::compositor_msg::{ReadyState, ScriptListener};
|
||||
use servo_msg::constellation_msg::PipelineId;
|
||||
use servo_msg::constellation_msg::{ConstellationChan, NavigateMsg, PipelineId, ResizedWindowMsg, LoadUrlMsg};
|
||||
use servo_msg::constellation_msg;
|
||||
use gfx::opts::Opts;
|
||||
|
||||
|
@ -40,11 +38,11 @@ use servo_util::{time, url};
|
|||
use servo_util::time::profile;
|
||||
use servo_util::time::ProfilerChan;
|
||||
|
||||
use extra::future::from_value;
|
||||
use extra::time::precise_time_s;
|
||||
use extra::arc;
|
||||
|
||||
use constellation::SendableFrameTree;
|
||||
use pipeline::Pipeline;
|
||||
use compositing::compositor_layer::CompositorLayer;
|
||||
|
||||
mod quadtree;
|
||||
|
@ -86,10 +84,12 @@ impl RenderListener for CompositorChan {
|
|||
}
|
||||
|
||||
fn new_layer(&self, id: PipelineId, page_size: Size2D<uint>) {
|
||||
self.chan.send(NewLayer(id, page_size))
|
||||
let Size2D { width, height } = page_size;
|
||||
self.chan.send(NewLayer(id, Size2D(width as f32, height as f32)))
|
||||
}
|
||||
fn resize_layer(&self, id: PipelineId, page_size: Size2D<uint>) {
|
||||
self.chan.send(ResizeLayer(id, page_size))
|
||||
let Size2D { width, height } = page_size;
|
||||
self.chan.send(ResizeLayer(id, Size2D(width as f32, height as f32)))
|
||||
}
|
||||
fn delete_layer(&self, id: PipelineId) {
|
||||
self.chan.send(DeleteLayer(id))
|
||||
|
@ -130,9 +130,9 @@ pub enum Msg {
|
|||
|
||||
// TODO: Attach epochs to these messages
|
||||
/// Alerts the compositor that there is a new layer to be rendered.
|
||||
NewLayer(PipelineId, Size2D<uint>),
|
||||
NewLayer(PipelineId, Size2D<f32>),
|
||||
/// Alerts the compositor that the specified layer has changed size.
|
||||
ResizeLayer(PipelineId, Size2D<uint>),
|
||||
ResizeLayer(PipelineId, Size2D<f32>),
|
||||
/// Alerts the compositor that the specified layer has been deleted.
|
||||
DeleteLayer(PipelineId),
|
||||
/// Invalidate a rect for a given layer
|
||||
|
@ -145,7 +145,7 @@ pub enum Msg {
|
|||
/// Alerts the compositor to the current status of rendering.
|
||||
ChangeRenderState(RenderState),
|
||||
/// Sets the channel to the current layout and render tasks, along with their id
|
||||
SetIds(SendableFrameTree, Chan<()>),
|
||||
SetIds(SendableFrameTree, Chan<()>, ConstellationChan),
|
||||
}
|
||||
|
||||
/// Azure surface wrapping to work with the layers infrastructure.
|
||||
|
@ -207,7 +207,7 @@ impl CompositorTask {
|
|||
let root_layer = @mut ContainerLayer();
|
||||
let window_size = window.size();
|
||||
let mut scene = Scene(ContainerLayerKind(root_layer), window_size, identity());
|
||||
let mut window_size = Size2D(window_size.width as int, window_size.height as int);
|
||||
let mut window_size = Size2D(window_size.width as uint, window_size.height as uint);
|
||||
let mut done = false;
|
||||
let mut recomposite = false;
|
||||
|
||||
|
@ -216,13 +216,9 @@ impl CompositorTask {
|
|||
let mut zoom_action = false;
|
||||
let mut zoom_time = 0f;
|
||||
|
||||
// Channel to the outermost frame's pipeline.
|
||||
// FIXME: Events are only forwarded to this pipeline, but they should be
|
||||
// routed to the appropriate pipeline via the constellation.
|
||||
let mut pipeline: Option<Pipeline> = None;
|
||||
|
||||
// The root CompositorLayer
|
||||
let mut compositor_layer: Option<CompositorLayer> = None;
|
||||
let mut constellation_chan: Option<ConstellationChan> = None;
|
||||
|
||||
// Get BufferRequests from each layer.
|
||||
let ask_for_tiles = || {
|
||||
|
@ -243,9 +239,22 @@ impl CompositorTask {
|
|||
ChangeReadyState(ready_state) => window.set_ready_state(ready_state),
|
||||
ChangeRenderState(render_state) => window.set_render_state(render_state),
|
||||
|
||||
SetIds(frame_tree, response_chan) => {
|
||||
pipeline = Some(frame_tree.pipeline);
|
||||
SetIds(frame_tree, response_chan, new_constellation_chan) => {
|
||||
response_chan.send(());
|
||||
|
||||
// This assumes there is at most one child, which should be the case.
|
||||
match root_layer.first_child {
|
||||
Some(old_layer) => root_layer.remove_child(old_layer),
|
||||
None => {}
|
||||
}
|
||||
|
||||
let layer = CompositorLayer::from_frame_tree(frame_tree,
|
||||
self.opts.tile_size,
|
||||
Some(10000000u));
|
||||
root_layer.add_child(ContainerLayerKind(layer.root_layer));
|
||||
compositor_layer = Some(layer);
|
||||
|
||||
constellation_chan = Some(new_constellation_chan);
|
||||
}
|
||||
|
||||
GetSize(chan) => {
|
||||
|
@ -259,12 +268,12 @@ impl CompositorTask {
|
|||
// FIXME: This should create an additional layer instead of replacing the current one.
|
||||
// Once ResizeLayer messages are set up, we can switch to the new functionality.
|
||||
|
||||
let p = match pipeline {
|
||||
Some(ref pipeline) => pipeline,
|
||||
let p = match compositor_layer {
|
||||
Some(ref compositor_layer) => compositor_layer.pipeline.clone(),
|
||||
None => fail!("Compositor: Received new layer without initialized pipeline"),
|
||||
};
|
||||
let page_size = Size2D(new_size.width as f32, new_size.height as f32);
|
||||
let new_layer = CompositorLayer::new(p.clone(), Some(page_size),
|
||||
let new_layer = CompositorLayer::new(p, Some(page_size),
|
||||
self.opts.tile_size, Some(10000000u));
|
||||
|
||||
let current_child = root_layer.first_child;
|
||||
|
@ -284,8 +293,9 @@ impl CompositorTask {
|
|||
Some(ref mut layer) => {
|
||||
let page_window = Size2D(window_size.width as f32 / world_zoom,
|
||||
window_size.height as f32 / world_zoom);
|
||||
assert!(layer.resize(id, Size2D(new_size.width as f32,
|
||||
new_size.height as f32),
|
||||
assert!(layer.resize(id,
|
||||
Size2D(new_size.width as f32,
|
||||
new_size.height as f32),
|
||||
page_window));
|
||||
ask_for_tiles();
|
||||
}
|
||||
|
@ -340,12 +350,12 @@ impl CompositorTask {
|
|||
IdleWindowEvent => {}
|
||||
|
||||
ResizeWindowEvent(width, height) => {
|
||||
let new_size = Size2D(width as int, height as int);
|
||||
let new_size = Size2D(width, height);
|
||||
if window_size != new_size {
|
||||
debug!("osmain: window resized to %ux%u", width, height);
|
||||
window_size = new_size;
|
||||
match pipeline {
|
||||
Some(ref pipeline) => pipeline.script_chan.send(SendEventMsg(pipeline.id.clone(), ResizeEvent(width, height))),
|
||||
match constellation_chan {
|
||||
Some(ref chan) => chan.send(ResizedWindowMsg(new_size)),
|
||||
None => error!("Compositor: Recieved resize event without initialized layout chan"),
|
||||
}
|
||||
} else {
|
||||
|
@ -355,8 +365,14 @@ impl CompositorTask {
|
|||
|
||||
LoadUrlWindowEvent(url_string) => {
|
||||
debug!("osmain: loading URL `%s`", url_string);
|
||||
match pipeline {
|
||||
Some(ref pipeline) => pipeline.script_chan.send(LoadMsg(pipeline.id.clone(), url::make_url(url_string.to_str(), None))),
|
||||
let root_pipeline_id = match compositor_layer {
|
||||
Some(ref layer) => layer.pipeline.id.clone(),
|
||||
None => fail!("Compositor: Received LoadUrlWindowEvent without initialized compositor layers"),
|
||||
};
|
||||
match constellation_chan {
|
||||
Some(ref chan) => chan.send(LoadUrlMsg(root_pipeline_id,
|
||||
url::make_url(url_string.to_str(), None),
|
||||
from_value(window_size))),
|
||||
None => error!("Compositor: Recieved loadurl event without initialized layout chan"),
|
||||
}
|
||||
}
|
||||
|
@ -413,8 +429,8 @@ impl CompositorTask {
|
|||
windowing::Forward => constellation_msg::Forward,
|
||||
windowing::Back => constellation_msg::Back,
|
||||
};
|
||||
match pipeline {
|
||||
Some(ref pipeline) => pipeline.script_chan.send(NavigateMsg(direction)),
|
||||
match constellation_chan {
|
||||
Some(ref chan) => chan.send(NavigateMsg(direction)),
|
||||
None => error!("Compositor: Recieved navigation event without initialized layout chan"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use compositing::{CompositorChan, SetIds};
|
||||
use compositing::{CompositorChan, SetIds, ResizeLayer};
|
||||
use script::dom::event::ResizeEvent;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::comm;
|
||||
|
@ -12,19 +13,19 @@ use geom::size::Size2D;
|
|||
use geom::rect::Rect;
|
||||
use gfx::opts::Opts;
|
||||
use pipeline::Pipeline;
|
||||
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg};
|
||||
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FrameRectMsg};
|
||||
use servo_msg::constellation_msg::{InitLoadUrlMsg, LoadIframeUrlMsg, LoadUrlMsg};
|
||||
use servo_msg::constellation_msg::{Msg, NavigateMsg};
|
||||
use servo_msg::constellation_msg::{PipelineId, RendererReadyMsg, ResizedWindowBroadcast, SubpageId};
|
||||
use servo_msg::constellation_msg::{PipelineId, RendererReadyMsg, ResizedWindowMsg, SubpageId};
|
||||
use servo_msg::constellation_msg;
|
||||
use script::script_task::{ResizeInactiveMsg, ExecuteMsg};
|
||||
use script::script_task::{SendEventMsg, ResizeInactiveMsg, ExecuteMsg};
|
||||
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
|
||||
use servo_net::resource_task::ResourceTask;
|
||||
use servo_net::resource_task;
|
||||
use servo_util::time::ProfilerChan;
|
||||
use std::hashmap::HashMap;
|
||||
use std::hashmap::{HashMap, HashSet};
|
||||
use std::util::replace;
|
||||
use extra::future::from_value;
|
||||
use extra::future::{Future, from_value};
|
||||
|
||||
/// Maintains the pipelines and navigation context and grants permission to composite
|
||||
pub struct Constellation {
|
||||
|
@ -167,7 +168,7 @@ impl Iterator<@mut FrameTree> for FrameTreeIterator {
|
|||
fn next(&mut self) -> Option<@mut FrameTree> {
|
||||
if !self.stack.is_empty() {
|
||||
let next = self.stack.pop();
|
||||
for next.children.iter().advance |&ChildFrameTree { frame_tree, _ }| {
|
||||
for &ChildFrameTree { frame_tree, _ } in next.children.iter() {
|
||||
self.stack.push(frame_tree);
|
||||
}
|
||||
Some(next)
|
||||
|
@ -318,328 +319,407 @@ impl Constellation {
|
|||
/// Handles loading pages, navigation, and granting access to the compositor
|
||||
fn handle_request(&mut self, request: Msg) -> bool {
|
||||
match request {
|
||||
|
||||
ExitMsg(sender) => {
|
||||
for (_id, ref pipeline) in self.pipelines.iter() {
|
||||
pipeline.exit();
|
||||
}
|
||||
self.image_cache_task.exit();
|
||||
self.resource_task.send(resource_task::Exit);
|
||||
|
||||
sender.send(());
|
||||
return false
|
||||
self.handle_exit(sender);
|
||||
return false;
|
||||
}
|
||||
|
||||
// This should only be called once per constellation, and only by the browser
|
||||
InitLoadUrlMsg(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.opts.clone(),
|
||||
{
|
||||
let size = self.compositor_chan.get_size();
|
||||
from_value(Size2D(size.width as uint, size.height as uint))
|
||||
});
|
||||
if url.path.ends_with(".js") {
|
||||
pipeline.script_chan.send(ExecuteMsg(pipeline.id, url));
|
||||
} else {
|
||||
pipeline.load(url, Some(constellation_msg::Load));
|
||||
|
||||
self.pending_frames.push(FrameChange{
|
||||
before: None,
|
||||
after: @mut FrameTree {
|
||||
pipeline: pipeline,
|
||||
parent: None,
|
||||
children: ~[],
|
||||
},
|
||||
});
|
||||
}
|
||||
self.pipelines.insert(pipeline.id, pipeline);
|
||||
self.handle_init_load(url);
|
||||
}
|
||||
// A layout assigned a size and position to a subframe. This needs to be reflected by all
|
||||
// frame trees in the navigation context containing the subframe.
|
||||
FrameRectMsg(pipeline_id, subpage_id, rect) => {
|
||||
self.handle_frame_rect_msg(pipeline_id, subpage_id, rect);
|
||||
}
|
||||
|
||||
LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, size_future) => {
|
||||
// A message from the script associated with pipeline_id that it has
|
||||
// parsed an iframe during html parsing. This iframe will result in a
|
||||
// new pipeline being spawned and a frame tree being added to pipeline_id's
|
||||
// frame tree's children. This message is never the result of a link clicked
|
||||
// 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 matching_navi_frames = self.navigation_context.find_all(source_pipeline_id);
|
||||
let matching_pending_frames = do self.pending_frames.iter().filter_map |frame_change| {
|
||||
frame_change.after.find_mut(source_pipeline_id)
|
||||
};
|
||||
matching_navi_frames.move_iter().chain(matching_pending_frames).collect()
|
||||
};
|
||||
|
||||
if frame_trees.is_empty() {
|
||||
fail!("Constellation: source pipeline id of LoadIframeUrlMsg is not in
|
||||
navigation context, nor is it in a pending frame. This should be
|
||||
impossible.");
|
||||
}
|
||||
|
||||
let next_pipeline_id = self.get_next_pipeline_id();
|
||||
|
||||
// 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:
|
||||
source Id of LoadIframeUrlMsg does have an associated pipeline in
|
||||
constellation. This should be impossible.");
|
||||
|
||||
let source_url = source_pipeline.url.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.");
|
||||
|
||||
// FIXME(tkuehn): Need to follow the standardized spec for checking same-origin
|
||||
let pipeline = @mut if (source_url.host == url.host &&
|
||||
source_url.port == url.port) {
|
||||
// Reuse the script task if same-origin url's
|
||||
Pipeline::with_script(next_pipeline_id,
|
||||
Some(subpage_id),
|
||||
self.chan.clone(),
|
||||
self.compositor_chan.clone(),
|
||||
self.image_cache_task.clone(),
|
||||
self.profiler_chan.clone(),
|
||||
self.opts.clone(),
|
||||
source_pipeline,
|
||||
size_future)
|
||||
} else {
|
||||
// Create a new script task if not same-origin url's
|
||||
Pipeline::create(next_pipeline_id,
|
||||
Some(subpage_id),
|
||||
self.chan.clone(),
|
||||
self.compositor_chan.clone(),
|
||||
self.image_cache_task.clone(),
|
||||
self.resource_task.clone(),
|
||||
self.profiler_chan.clone(),
|
||||
self.opts.clone(),
|
||||
size_future)
|
||||
};
|
||||
|
||||
if url.path.ends_with(".js") {
|
||||
pipeline.execute(url);
|
||||
} else {
|
||||
pipeline.load(url, None);
|
||||
}
|
||||
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: ~[],
|
||||
},
|
||||
rect: rect,
|
||||
});
|
||||
}
|
||||
self.pipelines.insert(pipeline.id, pipeline);
|
||||
self.handle_load_iframe_url_msg(url, source_pipeline_id, subpage_id, size_future);
|
||||
}
|
||||
|
||||
// Load a new page, usually -- but not always -- from a mouse click or typed url
|
||||
// If there is already a pending page (self.pending_frames), it will not be overridden;
|
||||
// However, if the id is not encompassed by another change, it will be.
|
||||
LoadUrlMsg(source_id, url, size_future) => {
|
||||
debug!("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_mut(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.");
|
||||
|
||||
for frame_change in self.pending_frames.iter() {
|
||||
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_mut(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) {
|
||||
// id that sent load msg is being changed already; abort
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 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.clone();
|
||||
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.opts.clone(),
|
||||
size_future);
|
||||
|
||||
if url.path.ends_with(".js") {
|
||||
pipeline.script_chan.send(ExecuteMsg(pipeline.id, url));
|
||||
} else {
|
||||
pipeline.load(url, Some(constellation_msg::Load));
|
||||
|
||||
self.pending_frames.push(FrameChange{
|
||||
before: Some(source_id),
|
||||
after: @mut FrameTree {
|
||||
pipeline: pipeline,
|
||||
parent: parent,
|
||||
children: ~[],
|
||||
},
|
||||
});
|
||||
}
|
||||
self.pipelines.insert(pipeline.id, pipeline);
|
||||
self.handle_load_url_msg(source_id, url, size_future);
|
||||
}
|
||||
|
||||
// Handle a forward or back request
|
||||
NavigateMsg(direction) => {
|
||||
debug!("received message to navigate %?", direction);
|
||||
|
||||
// TODO(tkuehn): what is the "critical point" beyond which pending frames
|
||||
// should not be cleared? Currently, the behavior is that forward/back
|
||||
// navigation always has navigation priority, and after that new page loading is
|
||||
// first come, first served.
|
||||
let destination_frame = match direction {
|
||||
constellation_msg::Forward => {
|
||||
if self.navigation_context.next.is_empty() {
|
||||
debug!("no next page to navigate to");
|
||||
return true
|
||||
} else {
|
||||
let old = self.current_frame().get_ref();
|
||||
for frame in old.iter() {
|
||||
frame.pipeline.revoke_paint_permission();
|
||||
}
|
||||
}
|
||||
self.navigation_context.forward()
|
||||
}
|
||||
constellation_msg::Back => {
|
||||
if self.navigation_context.previous.is_empty() {
|
||||
debug!("no previous page to navigate to");
|
||||
return true
|
||||
} else {
|
||||
let old = self.current_frame().get_ref();
|
||||
for frame in old.iter() {
|
||||
frame.pipeline.revoke_paint_permission();
|
||||
}
|
||||
}
|
||||
self.navigation_context.back()
|
||||
}
|
||||
};
|
||||
|
||||
for frame in destination_frame.iter() {
|
||||
let pipeline = &frame.pipeline;
|
||||
pipeline.reload(Some(constellation_msg::Navigate));
|
||||
}
|
||||
self.grant_paint_permission(destination_frame);
|
||||
|
||||
self.handle_navigate_msg(direction);
|
||||
}
|
||||
|
||||
// Notification that rendering has finished and is requesting permission to paint.
|
||||
RendererReadyMsg(pipeline_id) => {
|
||||
// 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
|
||||
// when the message originates from a pending frame or the current frame.
|
||||
|
||||
for ¤t_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) {
|
||||
self.set_ids(current_frame);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the pending frame change whose new pipeline id is pipeline_id.
|
||||
// If it is not found, it simply means that this pipeline will not receive
|
||||
// permission to paint.
|
||||
let pending_index = do self.pending_frames.rposition |frame_change| {
|
||||
frame_change.after.pipeline.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;
|
||||
|
||||
// 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(),
|
||||
};
|
||||
|
||||
// If there are frames to revoke permission from, do so now.
|
||||
match frame_change.before {
|
||||
Some(revoke_id) => {
|
||||
let current_frame = self.current_frame().unwrap();
|
||||
|
||||
let to_revoke = current_frame.find_mut(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();
|
||||
}
|
||||
|
||||
// If to_add is not the root frame, then replace revoked_frame with it
|
||||
if to_add.parent.is_some() {
|
||||
next_frame_tree.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;
|
||||
let to_add = Cell::new(to_add);
|
||||
for parent in parent.iter() {
|
||||
let parent = next_frame_tree.find_mut(parent.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.take(),
|
||||
rect: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
self.grant_paint_permission(next_frame_tree);
|
||||
}
|
||||
self.handle_renderer_ready_msg(pipeline_id);
|
||||
}
|
||||
|
||||
ResizedWindowBroadcast(new_size) => match *self.current_frame() {
|
||||
Some(ref current_frame) => {
|
||||
let current_frame_id = current_frame.pipeline.id.clone();
|
||||
for frame_tree in self.navigation_context.previous.iter() {
|
||||
let pipeline = &frame_tree.pipeline;
|
||||
if current_frame_id != pipeline.id {
|
||||
pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
||||
}
|
||||
}
|
||||
for frame_tree in self.navigation_context.next.iter() {
|
||||
let pipeline = &frame_tree.pipeline;
|
||||
if current_frame_id != pipeline.id {
|
||||
pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
for frame_tree in self.navigation_context.previous.iter() {
|
||||
frame_tree.pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
||||
}
|
||||
for frame_tree in self.navigation_context.next.iter() {
|
||||
frame_tree.pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
||||
}
|
||||
}
|
||||
ResizedWindowMsg(new_size) => {
|
||||
self.handle_resized_window_msg(new_size);
|
||||
}
|
||||
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn handle_exit(&self, sender: Chan<()>) {
|
||||
for (_id, ref pipeline) in self.pipelines.iter() {
|
||||
pipeline.exit();
|
||||
}
|
||||
self.image_cache_task.exit();
|
||||
self.resource_task.send(resource_task::Exit);
|
||||
|
||||
sender.send(());
|
||||
}
|
||||
|
||||
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.opts.clone(),
|
||||
{
|
||||
let size = self.compositor_chan.get_size();
|
||||
from_value(Size2D(size.width as uint, size.height as uint))
|
||||
});
|
||||
if url.path.ends_with(".js") {
|
||||
pipeline.script_chan.send(ExecuteMsg(pipeline.id, url));
|
||||
} else {
|
||||
pipeline.load(url, Some(constellation_msg::Load));
|
||||
|
||||
self.pending_frames.push(FrameChange{
|
||||
before: None,
|
||||
after: @mut FrameTree {
|
||||
pipeline: pipeline,
|
||||
parent: None,
|
||||
children: ~[],
|
||||
},
|
||||
});
|
||||
}
|
||||
self.pipelines.insert(pipeline.id, pipeline);
|
||||
}
|
||||
|
||||
fn handle_frame_rect_msg(&mut self, pipeline_id: PipelineId, subpage_id: SubpageId, rect: Rect<f32>) {
|
||||
let mut already_sent = HashSet::new();
|
||||
|
||||
// If the subframe is in the current frame tree, the compositor needs the new size
|
||||
let source_frame = self.current_frame().unwrap().find_mut(pipeline_id);
|
||||
for source_frame in source_frame.iter() {
|
||||
for child_frame_tree in source_frame.children.mut_iter() {
|
||||
let pipeline = &child_frame_tree.frame_tree.pipeline;
|
||||
if pipeline.subpage_id.expect("Constellation: child frame does not have a
|
||||
subpage id. This should not be possible.") == subpage_id {
|
||||
child_frame_tree.rect = Some(rect.clone());
|
||||
let Rect { size: Size2D { width, height }, _ } = rect;
|
||||
pipeline.script_chan.send(SendEventMsg(pipeline.id.clone(),
|
||||
ResizeEvent(width as uint,
|
||||
height as uint)));
|
||||
self.compositor_chan.send(ResizeLayer(pipeline.id, rect.size));
|
||||
already_sent.insert(pipeline.id.clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Go through the navigation context and tell each associated pipeline to resize.
|
||||
let frame_trees: ~[@mut FrameTree] = {
|
||||
let matching_navi_frames = self.navigation_context.find_all(pipeline_id);
|
||||
let matching_pending_frames = do self.pending_frames.iter().filter_map |frame_change| {
|
||||
frame_change.after.find_mut(pipeline_id)
|
||||
};
|
||||
matching_navi_frames.move_iter().chain(matching_pending_frames).collect()
|
||||
};
|
||||
for frame_tree in frame_trees.iter() {
|
||||
for child_frame_tree in frame_tree.children.mut_iter() {
|
||||
let pipeline = &child_frame_tree.frame_tree.pipeline;
|
||||
if pipeline.subpage_id.expect("Constellation: child frame does not have a
|
||||
subpage id. This should not be possible.") == subpage_id {
|
||||
child_frame_tree.rect = Some(rect.clone());
|
||||
if !already_sent.contains(&pipeline.id) {
|
||||
let Size2D { width, height } = rect.size;
|
||||
pipeline.script_chan.send(ResizeInactiveMsg(pipeline.id.clone(),
|
||||
Size2D(width as uint, height as uint)));
|
||||
already_sent.insert(pipeline.id.clone());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, if no pipelines were sent a resize msg, then this subpage id
|
||||
// should be added to pending sizes
|
||||
if already_sent.len() == 0 {
|
||||
self.pending_sizes.insert((pipeline_id, subpage_id), rect);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_load_iframe_url_msg(&mut self,
|
||||
url: Url,
|
||||
source_pipeline_id: PipelineId,
|
||||
subpage_id: SubpageId,
|
||||
size_future: Future<Size2D<uint>>) {
|
||||
// A message from the script associated with pipeline_id that it has
|
||||
// parsed an iframe during html parsing. This iframe will result in a
|
||||
// new pipeline being spawned and a frame tree being added to pipeline_id's
|
||||
// frame tree's children. This message is never the result of a link clicked
|
||||
// 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 matching_navi_frames = self.navigation_context.find_all(source_pipeline_id);
|
||||
let matching_pending_frames = do self.pending_frames.iter().filter_map |frame_change| {
|
||||
frame_change.after.find_mut(source_pipeline_id)
|
||||
};
|
||||
matching_navi_frames.move_iter().chain(matching_pending_frames).collect()
|
||||
};
|
||||
|
||||
if frame_trees.is_empty() {
|
||||
fail!("Constellation: source pipeline id of LoadIframeUrlMsg is not in
|
||||
navigation context, nor is it in a pending frame. This should be
|
||||
impossible.");
|
||||
}
|
||||
|
||||
let next_pipeline_id = self.get_next_pipeline_id();
|
||||
|
||||
// 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:
|
||||
source Id of LoadIframeUrlMsg does have an associated pipeline in
|
||||
constellation. This should be impossible.");
|
||||
|
||||
let source_url = source_pipeline.url.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.");
|
||||
|
||||
// FIXME(tkuehn): Need to follow the standardized spec for checking same-origin
|
||||
let pipeline = @mut if (source_url.host == url.host &&
|
||||
source_url.port == url.port) {
|
||||
// Reuse the script task if same-origin url's
|
||||
Pipeline::with_script(next_pipeline_id,
|
||||
Some(subpage_id),
|
||||
self.chan.clone(),
|
||||
self.compositor_chan.clone(),
|
||||
self.image_cache_task.clone(),
|
||||
self.profiler_chan.clone(),
|
||||
self.opts.clone(),
|
||||
source_pipeline,
|
||||
size_future)
|
||||
} else {
|
||||
// Create a new script task if not same-origin url's
|
||||
Pipeline::create(next_pipeline_id,
|
||||
Some(subpage_id),
|
||||
self.chan.clone(),
|
||||
self.compositor_chan.clone(),
|
||||
self.image_cache_task.clone(),
|
||||
self.resource_task.clone(),
|
||||
self.profiler_chan.clone(),
|
||||
self.opts.clone(),
|
||||
size_future)
|
||||
};
|
||||
|
||||
if url.path.ends_with(".js") {
|
||||
pipeline.execute(url);
|
||||
} else {
|
||||
pipeline.load(url, None);
|
||||
}
|
||||
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: ~[],
|
||||
},
|
||||
rect: rect,
|
||||
});
|
||||
}
|
||||
self.pipelines.insert(pipeline.id, pipeline);
|
||||
}
|
||||
|
||||
fn handle_load_url_msg(&mut self, source_id: PipelineId, url: Url, size_future: Future<Size2D<uint>>) {
|
||||
debug!("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_mut(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.");
|
||||
|
||||
for frame_change in self.pending_frames.iter() {
|
||||
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_mut(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) {
|
||||
// id that sent load msg is being changed already; abort
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 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.clone();
|
||||
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.opts.clone(),
|
||||
size_future);
|
||||
|
||||
if url.path.ends_with(".js") {
|
||||
pipeline.script_chan.send(ExecuteMsg(pipeline.id, url));
|
||||
} else {
|
||||
pipeline.load(url, Some(constellation_msg::Load));
|
||||
|
||||
self.pending_frames.push(FrameChange{
|
||||
before: Some(source_id),
|
||||
after: @mut FrameTree {
|
||||
pipeline: pipeline,
|
||||
parent: parent,
|
||||
children: ~[],
|
||||
},
|
||||
});
|
||||
}
|
||||
self.pipelines.insert(pipeline.id, pipeline);
|
||||
}
|
||||
|
||||
fn handle_navigate_msg(&mut self, direction: constellation_msg::NavigationDirection) {
|
||||
debug!("received message to navigate %?", direction);
|
||||
|
||||
// TODO(tkuehn): what is the "critical point" beyond which pending frames
|
||||
// should not be cleared? Currently, the behavior is that forward/back
|
||||
// navigation always has navigation priority, and after that new page loading is
|
||||
// first come, first served.
|
||||
let destination_frame = match direction {
|
||||
constellation_msg::Forward => {
|
||||
if self.navigation_context.next.is_empty() {
|
||||
debug!("no next page to navigate to");
|
||||
return;
|
||||
} else {
|
||||
let old = self.current_frame().get_ref();
|
||||
for frame in old.iter() {
|
||||
frame.pipeline.revoke_paint_permission();
|
||||
}
|
||||
}
|
||||
self.navigation_context.forward()
|
||||
}
|
||||
constellation_msg::Back => {
|
||||
if self.navigation_context.previous.is_empty() {
|
||||
debug!("no previous page to navigate to");
|
||||
return;
|
||||
} else {
|
||||
let old = self.current_frame().get_ref();
|
||||
for frame in old.iter() {
|
||||
frame.pipeline.revoke_paint_permission();
|
||||
}
|
||||
}
|
||||
self.navigation_context.back()
|
||||
}
|
||||
};
|
||||
|
||||
for frame in destination_frame.iter() {
|
||||
let pipeline = &frame.pipeline;
|
||||
pipeline.reload(Some(constellation_msg::Navigate));
|
||||
}
|
||||
self.grant_paint_permission(destination_frame);
|
||||
|
||||
}
|
||||
|
||||
fn handle_renderer_ready_msg(&mut self, pipeline_id: PipelineId) {
|
||||
// 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
|
||||
// when the message originates from a pending frame or the current frame.
|
||||
|
||||
for ¤t_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) {
|
||||
self.set_ids(current_frame);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the pending frame change whose new pipeline id is pipeline_id.
|
||||
// If it is not found, it simply means that this pipeline will not receive
|
||||
// permission to paint.
|
||||
let pending_index = do self.pending_frames.rposition |frame_change| {
|
||||
frame_change.after.pipeline.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;
|
||||
|
||||
// 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(),
|
||||
};
|
||||
|
||||
// If there are frames to revoke permission from, do so now.
|
||||
match frame_change.before {
|
||||
Some(revoke_id) => {
|
||||
let current_frame = self.current_frame().unwrap();
|
||||
|
||||
let to_revoke = current_frame.find_mut(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();
|
||||
}
|
||||
|
||||
// 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() {
|
||||
next_frame_tree.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;
|
||||
let to_add = Cell::new(to_add);
|
||||
for parent in parent.iter() {
|
||||
let to_add = to_add.take();
|
||||
let subpage_id = to_add.pipeline.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_mut(parent.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,
|
||||
rect: rect,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
self.grant_paint_permission(next_frame_tree);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_resized_window_msg(&mut self, new_size: Size2D<uint>) {
|
||||
let mut already_seen = HashSet::new();
|
||||
for &@FrameTree { pipeline: ref pipeline, _ } in self.current_frame().iter() {
|
||||
let Size2D { width, height } = new_size;
|
||||
pipeline.script_chan.send(SendEventMsg(pipeline.id.clone(),
|
||||
ResizeEvent(width, height)));
|
||||
already_seen.insert(pipeline.id.clone());
|
||||
}
|
||||
for &@FrameTree { pipeline: ref pipeline, _ } in self.navigation_context.previous.iter()
|
||||
.chain(self.navigation_context.next.iter()) {
|
||||
if !already_seen.contains(&pipeline.id) {
|
||||
pipeline.script_chan.send(ResizeInactiveMsg(pipeline.id.clone(), new_size));
|
||||
already_seen.insert(pipeline.id.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// Give permission to paint to the new frame and all child frames
|
||||
|
@ -666,7 +746,7 @@ impl Constellation {
|
|||
|
||||
fn set_ids(&self, frame_tree: @mut FrameTree) {
|
||||
let (port, chan) = comm::stream();
|
||||
self.compositor_chan.send(SetIds(frame_tree.to_sendable(), chan));
|
||||
self.compositor_chan.send(SetIds(frame_tree.to_sendable(), chan, self.chan.clone()));
|
||||
port.recv();
|
||||
for frame in frame_tree.iter() {
|
||||
frame.pipeline.grant_paint_permission();
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::comm::{Chan, SharedChan};
|
|||
use extra::url::Url;
|
||||
use extra::future::Future;
|
||||
use geom::size::Size2D;
|
||||
use geom::rect::Rect;
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct ConstellationChan {
|
||||
|
@ -29,12 +30,12 @@ impl ConstellationChan {
|
|||
pub enum Msg {
|
||||
ExitMsg(Chan<()>),
|
||||
InitLoadUrlMsg(Url),
|
||||
//FrameRectMsg(PipelineId, SubpageId, Rect<?>),
|
||||
FrameRectMsg(PipelineId, SubpageId, Rect<f32>),
|
||||
LoadUrlMsg(PipelineId, Url, Future<Size2D<uint>>),
|
||||
LoadIframeUrlMsg(Url, PipelineId, SubpageId, Future<Size2D<uint>>),
|
||||
NavigateMsg(NavigationDirection),
|
||||
RendererReadyMsg(PipelineId),
|
||||
ResizedWindowBroadcast(Size2D<uint>),
|
||||
ResizedWindowMsg(Size2D<uint>),
|
||||
}
|
||||
|
||||
/// Represents the two different ways to which a page can be navigated
|
||||
|
|
|
@ -21,7 +21,7 @@ use layout_interface::{ReflowDocumentDamage, ReflowForDisplay, ReflowGoal};
|
|||
use layout_interface::ReflowMsg;
|
||||
use layout_interface;
|
||||
use servo_msg::constellation_msg::{ConstellationChan, LoadUrlMsg, NavigationDirection};
|
||||
use servo_msg::constellation_msg::{PipelineId, SubpageId, RendererReadyMsg, ResizedWindowBroadcast};
|
||||
use servo_msg::constellation_msg::{PipelineId, SubpageId, RendererReadyMsg};
|
||||
use servo_msg::constellation_msg::{LoadIframeUrlMsg};
|
||||
use servo_msg::constellation_msg;
|
||||
|
||||
|
@ -68,7 +68,7 @@ pub enum ScriptMsg {
|
|||
/// Notifies script that reflow is finished.
|
||||
ReflowCompleteMsg(PipelineId),
|
||||
/// Notifies script that window has been resized but to not take immediate action.
|
||||
ResizeInactiveMsg(Size2D<uint>),
|
||||
ResizeInactiveMsg(PipelineId, Size2D<uint>),
|
||||
/// Exits the constellation.
|
||||
ExitMsg,
|
||||
}
|
||||
|
@ -454,7 +454,7 @@ impl ScriptTask {
|
|||
FireTimerMsg(id, timer_data) => self.handle_fire_timer_msg(id, timer_data),
|
||||
NavigateMsg(direction) => self.handle_navigate_msg(direction),
|
||||
ReflowCompleteMsg(id) => self.handle_reflow_complete_msg(id),
|
||||
ResizeInactiveMsg(new_size) => self.handle_resize_inactive_msg(new_size),
|
||||
ResizeInactiveMsg(id, new_size) => self.handle_resize_inactive_msg(id, new_size),
|
||||
ExitMsg => {
|
||||
self.handle_exit_msg();
|
||||
return false
|
||||
|
@ -543,11 +543,13 @@ impl ScriptTask {
|
|||
}
|
||||
|
||||
/// Window was resized, but this script was not active, so don't reflow yet
|
||||
fn handle_resize_inactive_msg(&mut self, new_size: Size2D<uint>) {
|
||||
self.page_tree.page.window_size = from_value(new_size);
|
||||
let last_loaded_url = replace(&mut self.page_tree.page.url, None);
|
||||
fn handle_resize_inactive_msg(&mut self, id: PipelineId, new_size: Size2D<uint>) {
|
||||
let page = self.page_tree.find(id).expect("Received resize message for PipelineId not associated
|
||||
with a page in the page tree. This is a bug.").page;
|
||||
page.window_size = from_value(new_size);
|
||||
let last_loaded_url = replace(&mut page.url, None);
|
||||
for url in last_loaded_url.iter() {
|
||||
self.page_tree.page.url = Some((url.first(), true));
|
||||
page.url = Some((url.first(), true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -700,8 +702,6 @@ impl ScriptTask {
|
|||
page.damage(ReflowDocumentDamage);
|
||||
page.reflow(ReflowForDisplay, self.chan.clone(), self.compositor)
|
||||
}
|
||||
|
||||
self.constellation_chan.send(ResizedWindowBroadcast(page.window_size.get().clone()));
|
||||
}
|
||||
|
||||
// FIXME(pcwalton): This reflows the entire document and is not incremental-y.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue