mirror of
https://github.com/servo/servo.git
synced 2025-06-19 14:48:59 +01:00
auto merge of #1405 : pcwalton/servo/defuture, r=larsbergstrom
This will allow us to stop going to the DOM in order to handle iframe sizing. Instead we can just store the pipeline and frame IDs of iframes inside the flow tree itself. r? @kmcallister
This commit is contained in:
commit
aa1ebbbdb0
12 changed files with 243 additions and 197 deletions
|
@ -148,6 +148,7 @@ pub enum Msg {
|
|||
pub struct CompositorTask {
|
||||
opts: Opts,
|
||||
port: Port<Msg>,
|
||||
constellation_chan: ConstellationChan,
|
||||
profiler_chan: ProfilerChan,
|
||||
shutdown_chan: SharedChan<()>,
|
||||
}
|
||||
|
@ -155,12 +156,14 @@ pub struct CompositorTask {
|
|||
impl CompositorTask {
|
||||
pub fn new(opts: Opts,
|
||||
port: Port<Msg>,
|
||||
constellation_chan: ConstellationChan,
|
||||
profiler_chan: ProfilerChan,
|
||||
shutdown_chan: Chan<()>)
|
||||
-> CompositorTask {
|
||||
CompositorTask {
|
||||
opts: opts,
|
||||
port: port,
|
||||
constellation_chan: constellation_chan,
|
||||
profiler_chan: profiler_chan,
|
||||
shutdown_chan: SharedChan::new(shutdown_chan),
|
||||
}
|
||||
|
|
|
@ -2,41 +2,35 @@
|
|||
* 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::compositor_layer::CompositorLayer;
|
||||
use compositing::*;
|
||||
use platform::{Application, Window};
|
||||
|
||||
use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
|
||||
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
|
||||
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
|
||||
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
|
||||
|
||||
use servo_msg::constellation_msg::{ConstellationChan, NavigateMsg, ResizedWindowMsg, LoadUrlMsg};
|
||||
use servo_msg::constellation_msg;
|
||||
|
||||
use azure::azure_hl::SourceSurfaceMethods;
|
||||
use azure::azure_hl;
|
||||
use std::comm::Port;
|
||||
use std::num::Orderable;
|
||||
use std::vec;
|
||||
use std::path::Path;
|
||||
use std::rt::io::timer::Timer;
|
||||
use extra::time::precise_time_s;
|
||||
use geom::matrix::identity;
|
||||
use geom::point::Point2D;
|
||||
use geom::size::Size2D;
|
||||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
use layers::layers::{ContainerLayer, ContainerLayerKind};
|
||||
use layers::rendergl;
|
||||
use layers::scene::Scene;
|
||||
use opengles::gl2;
|
||||
use png;
|
||||
use servo_util::{time, url};
|
||||
use servo_msg::constellation_msg::{ConstellationChan, NavigateMsg, ResizedWindowMsg, LoadUrlMsg};
|
||||
use servo_msg::constellation_msg;
|
||||
use servo_util::time::profile;
|
||||
|
||||
use extra::future::Future;
|
||||
use extra::time::precise_time_s;
|
||||
|
||||
use compositing::compositor_layer::CompositorLayer;
|
||||
|
||||
use compositing::*;
|
||||
use servo_util::{time, url};
|
||||
use std::comm::Port;
|
||||
use std::num::Orderable;
|
||||
use std::path::Path;
|
||||
use std::rt::io::timer::Timer;
|
||||
use std::vec;
|
||||
|
||||
/// Starts the compositor, which listens for messages on the specified port.
|
||||
pub fn run_compositor(compositor: &CompositorTask) {
|
||||
|
@ -63,7 +57,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
|
|||
|
||||
// The root CompositorLayer
|
||||
let mut compositor_layer: Option<CompositorLayer> = None;
|
||||
let mut constellation_chan: Option<ConstellationChan> = None;
|
||||
let mut constellation_chan: ConstellationChan = compositor.constellation_chan.clone();
|
||||
|
||||
// Get BufferRequests from each layer.
|
||||
let ask_for_tiles = || {
|
||||
|
@ -128,7 +122,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
|
|||
window_size.height as uint);
|
||||
new_constellation_chan.send(ResizedWindowMsg(window_size));
|
||||
|
||||
constellation_chan = Some(new_constellation_chan);
|
||||
constellation_chan = new_constellation_chan;
|
||||
}
|
||||
|
||||
GetGraphicsMetadata(chan) => chan.send(Some(azure_hl::current_graphics_metadata())),
|
||||
|
@ -252,10 +246,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
|
|||
if window_size != new_size {
|
||||
debug!("osmain: window resized to {:u}x{:u}", width, height);
|
||||
window_size = new_size;
|
||||
match constellation_chan {
|
||||
Some(ref chan) => chan.send(ResizedWindowMsg(new_size)),
|
||||
None => error!("Compositor: Received resize event without initialized layout chan"),
|
||||
}
|
||||
constellation_chan.send(ResizedWindowMsg(new_size))
|
||||
} else {
|
||||
debug!("osmain: dropping window resize since size is still {:u}x{:u}", width, height);
|
||||
}
|
||||
|
@ -267,12 +258,8 @@ pub fn run_compositor(compositor: &CompositorTask) {
|
|||
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),
|
||||
Future::from_value(window_size))),
|
||||
None => error!("Compositor: Received loadurl event without initialized layout chan"),
|
||||
}
|
||||
constellation_chan.send(LoadUrlMsg(root_pipeline_id,
|
||||
url::make_url(url_string.to_str(), None)))
|
||||
}
|
||||
|
||||
MouseWindowEventClass(mouse_window_event) => {
|
||||
|
@ -327,10 +314,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
|
|||
windowing::Forward => constellation_msg::Forward,
|
||||
windowing::Back => constellation_msg::Back,
|
||||
};
|
||||
match constellation_chan {
|
||||
Some(ref chan) => chan.send(NavigateMsg(direction)),
|
||||
None => error!("Compositor: Received navigation event without initialized layout chan"),
|
||||
}
|
||||
constellation_chan.send(NavigateMsg(direction))
|
||||
}
|
||||
|
||||
FinishedWindowEvent => {
|
||||
|
@ -403,6 +387,9 @@ pub fn run_compositor(compositor: &CompositorTask) {
|
|||
if exit { done = true; }
|
||||
};
|
||||
|
||||
// Tell the constellation about the initial window size.
|
||||
constellation_chan.send(ResizedWindowMsg(window_size));
|
||||
|
||||
// Enter the main event loop.
|
||||
let mut tm = Timer::new().unwrap();
|
||||
while !done {
|
||||
|
|
|
@ -4,11 +4,17 @@
|
|||
|
||||
use compositing::*;
|
||||
|
||||
use geom::size::Size2D;
|
||||
use servo_msg::constellation_msg::ResizedWindowMsg;
|
||||
|
||||
/// Starts the compositor, which listens for messages on the specified port.
|
||||
///
|
||||
/// This is the null compositor which doesn't draw anything to the screen.
|
||||
/// It's intended for headless testing.
|
||||
pub fn run_compositor(compositor: &CompositorTask) {
|
||||
// Tell the constellation about the initial fake size.
|
||||
compositor.constellation_chan.send(ResizedWindowMsg(Size2D(640u, 480u)));
|
||||
|
||||
loop {
|
||||
match compositor.port.recv() {
|
||||
Exit => break,
|
||||
|
|
|
@ -4,28 +4,27 @@
|
|||
|
||||
use compositing::{CompositorChan, SetIds, SetLayerClipRect};
|
||||
|
||||
use std::comm;
|
||||
use std::comm::Port;
|
||||
use std::task::spawn_with;
|
||||
use geom::size::Size2D;
|
||||
use extra::url::Url;
|
||||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
use gfx::opts::Opts;
|
||||
use pipeline::Pipeline;
|
||||
use script::script_task::{ResizeMsg, ResizeInactiveMsg};
|
||||
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, FrameRectMsg};
|
||||
use servo_msg::constellation_msg::{IFrameSandboxState, InitLoadUrlMsg, LoadIframeUrlMsg, LoadUrlMsg};
|
||||
use servo_msg::constellation_msg::{Msg, NavigateMsg, NavigationType, IFrameUnsandboxed};
|
||||
use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
|
||||
use servo_msg::constellation_msg::{LoadIframeUrlMsg, LoadUrlMsg, Msg, NavigateMsg, NavigationType};
|
||||
use servo_msg::constellation_msg::{PipelineId, RendererReadyMsg, ResizedWindowMsg, SubpageId};
|
||||
use servo_msg::constellation_msg;
|
||||
use script::script_task::{ResizeMsg, ResizeInactiveMsg};
|
||||
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 servo_util::url::make_url;
|
||||
use std::comm::Port;
|
||||
use std::comm;
|
||||
use std::hashmap::{HashMap, HashSet};
|
||||
use std::task::spawn_with;
|
||||
use std::util::replace;
|
||||
use extra::url::Url;
|
||||
use extra::future::Future;
|
||||
|
||||
/// Maintains the pipelines and navigation context and grants permission to composite
|
||||
pub struct Constellation {
|
||||
|
@ -249,18 +248,27 @@ impl NavigationContext {
|
|||
}
|
||||
|
||||
impl Constellation {
|
||||
pub fn start(compositor_chan: CompositorChan,
|
||||
pub fn start(constellation_port: Port<Msg>,
|
||||
constellation_chan: ConstellationChan,
|
||||
compositor_chan: CompositorChan,
|
||||
opts: &Opts,
|
||||
resource_task: ResourceTask,
|
||||
image_cache_task: ImageCacheTask,
|
||||
profiler_chan: ProfilerChan)
|
||||
-> ConstellationChan {
|
||||
let (constellation_port, constellation_chan) = special_stream!(ConstellationChan);
|
||||
do spawn_with((constellation_port, constellation_chan.clone(),
|
||||
compositor_chan, resource_task, image_cache_task,
|
||||
profiler_chan, opts.clone()))
|
||||
|(constellation_port, constellation_chan, compositor_chan, resource_task,
|
||||
image_cache_task, profiler_chan, opts)| {
|
||||
profiler_chan: ProfilerChan) {
|
||||
do spawn_with((constellation_port,
|
||||
constellation_chan.clone(),
|
||||
compositor_chan,
|
||||
resource_task,
|
||||
image_cache_task,
|
||||
profiler_chan,
|
||||
opts.clone()))
|
||||
|(constellation_port,
|
||||
constellation_chan,
|
||||
compositor_chan,
|
||||
resource_task,
|
||||
image_cache_task,
|
||||
profiler_chan,
|
||||
opts)| {
|
||||
let mut constellation = Constellation {
|
||||
chan: constellation_chan,
|
||||
request_port: constellation_port,
|
||||
|
@ -278,7 +286,6 @@ impl Constellation {
|
|||
};
|
||||
constellation.run();
|
||||
}
|
||||
constellation_chan
|
||||
}
|
||||
|
||||
fn run(&mut self) {
|
||||
|
@ -324,32 +331,38 @@ impl Constellation {
|
|||
}
|
||||
// This should only be called once per constellation, and only by the browser
|
||||
InitLoadUrlMsg(url) => {
|
||||
debug!("constellation got init load URL message");
|
||||
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.
|
||||
// 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) => {
|
||||
debug!("constellation got frame rect message");
|
||||
self.handle_frame_rect_msg(pipeline_id, subpage_id, rect);
|
||||
}
|
||||
LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, size_future, sandbox) => {
|
||||
self.handle_load_iframe_url_msg(url, source_pipeline_id, subpage_id, size_future, sandbox);
|
||||
LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, sandbox) => {
|
||||
debug!("constellation got iframe URL load message");
|
||||
self.handle_load_iframe_url_msg(url, source_pipeline_id, subpage_id, sandbox);
|
||||
}
|
||||
// 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) => {
|
||||
self.handle_load_url_msg(source_id, url, size_future);
|
||||
LoadUrlMsg(source_id, url) => {
|
||||
debug!("constellation got URL load message");
|
||||
self.handle_load_url_msg(source_id, url);
|
||||
}
|
||||
// Handle a forward or back request
|
||||
NavigateMsg(direction) => {
|
||||
debug!("constellation got navigation message");
|
||||
self.handle_navigate_msg(direction);
|
||||
}
|
||||
// Notification that rendering has finished and is requesting permission to paint.
|
||||
RendererReadyMsg(pipeline_id) => {
|
||||
debug!("constellation got renderer ready message");
|
||||
self.handle_renderer_ready_msg(pipeline_id);
|
||||
}
|
||||
|
||||
ResizedWindowMsg(new_size) => {
|
||||
debug!("constellation got window resize message");
|
||||
self.handle_resized_window_msg(new_size);
|
||||
}
|
||||
}
|
||||
|
@ -375,8 +388,7 @@ impl Constellation {
|
|||
self.image_cache_task.clone(),
|
||||
self.resource_task.clone(),
|
||||
self.profiler_chan.clone(),
|
||||
self.opts.clone(),
|
||||
Future::from_value(self.window_size));
|
||||
self.opts.clone());
|
||||
let failure = ~"about:failure";
|
||||
let url = make_url(failure, None);
|
||||
pipeline.load(url);
|
||||
|
@ -397,11 +409,10 @@ impl Constellation {
|
|||
self.image_cache_task.clone(),
|
||||
self.resource_task.clone(),
|
||||
self.profiler_chan.clone(),
|
||||
self.opts.clone(),
|
||||
Future::from_value(self.window_size));
|
||||
self.opts.clone());
|
||||
pipeline.load(url);
|
||||
|
||||
self.pending_frames.push(FrameChange{
|
||||
self.pending_frames.push(FrameChange {
|
||||
before: None,
|
||||
after: @mut FrameTree {
|
||||
pipeline: pipeline,
|
||||
|
@ -476,7 +487,6 @@ impl Constellation {
|
|||
url: Url,
|
||||
source_pipeline_id: PipelineId,
|
||||
subpage_id: SubpageId,
|
||||
size_future: Future<Size2D<uint>>,
|
||||
sandbox: IFrameSandboxState) {
|
||||
// A message from the script associated with pipeline_id that it has
|
||||
// parsed an iframe during html parsing. This iframe will result in a
|
||||
|
@ -524,8 +534,7 @@ impl Constellation {
|
|||
self.image_cache_task.clone(),
|
||||
self.profiler_chan.clone(),
|
||||
self.opts.clone(),
|
||||
source_pipeline,
|
||||
size_future)
|
||||
source_pipeline)
|
||||
} else {
|
||||
debug!("Constellation: loading cross-origin iframe at {:?}", url);
|
||||
// Create a new script task if not same-origin url's
|
||||
|
@ -536,8 +545,7 @@ impl Constellation {
|
|||
self.image_cache_task.clone(),
|
||||
self.resource_task.clone(),
|
||||
self.profiler_chan.clone(),
|
||||
self.opts.clone(),
|
||||
size_future)
|
||||
self.opts.clone())
|
||||
};
|
||||
|
||||
debug!("Constellation: sending load msg to pipeline {:?}", pipeline.id);
|
||||
|
@ -556,7 +564,7 @@ impl Constellation {
|
|||
self.pipelines.insert(pipeline.id, pipeline);
|
||||
}
|
||||
|
||||
fn handle_load_url_msg(&mut self, source_id: PipelineId, url: Url, size_future: Future<Size2D<uint>>) {
|
||||
fn handle_load_url_msg(&mut self, source_id: PipelineId, url: Url) {
|
||||
debug!("Constellation: received message to load {:s}", url.to_str());
|
||||
// Make sure no pending page would be overridden.
|
||||
let source_frame = self.current_frame().get_ref().find(source_id).expect(
|
||||
|
@ -590,8 +598,7 @@ impl Constellation {
|
|||
self.image_cache_task.clone(),
|
||||
self.resource_task.clone(),
|
||||
self.profiler_chan.clone(),
|
||||
self.opts.clone(),
|
||||
size_future);
|
||||
self.opts.clone());
|
||||
|
||||
pipeline.load(url);
|
||||
|
||||
|
@ -723,13 +730,16 @@ impl Constellation {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.grant_paint_permission(next_frame_tree, frame_change.navigation_type);
|
||||
}
|
||||
}
|
||||
|
||||
/// Called when the window is resized.
|
||||
fn handle_resized_window_msg(&mut self, new_size: Size2D<uint>) {
|
||||
let mut already_seen = HashSet::new();
|
||||
for &@FrameTree { pipeline: pipeline, _ } in self.current_frame().iter() {
|
||||
debug!("constellation sending resize message to active frame");
|
||||
pipeline.script_chan.send(ResizeMsg(pipeline.id, new_size));
|
||||
already_seen.insert(pipeline.id);
|
||||
}
|
||||
|
@ -737,10 +747,22 @@ impl Constellation {
|
|||
.chain(self.navigation_context.next.iter()) {
|
||||
let pipeline = &frame_tree.pipeline;
|
||||
if !already_seen.contains(&pipeline.id) {
|
||||
debug!("constellation sending resize message to inactive frame");
|
||||
pipeline.script_chan.send(ResizeInactiveMsg(pipeline.id, new_size));
|
||||
already_seen.insert(pipeline.id);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any pending outermost frames, then tell them to resize. (This is how the
|
||||
// initial window size gets sent to the first page loaded, giving it permission to reflow.)
|
||||
for change in self.pending_frames.iter() {
|
||||
let frame_tree = change.after;
|
||||
if frame_tree.parent.is_none() {
|
||||
debug!("constellation sending resize message to pending outer frame");
|
||||
frame_tree.pipeline.script_chan.send(ResizeMsg(frame_tree.pipeline.id, new_size))
|
||||
}
|
||||
}
|
||||
|
||||
self.window_size = new_size;
|
||||
}
|
||||
|
||||
|
|
|
@ -295,7 +295,9 @@ impl LayoutTask {
|
|||
}
|
||||
}
|
||||
PrepareToExitMsg(response_chan) => {
|
||||
self.prepare_to_exit(response_chan)
|
||||
debug!("layout: PrepareToExitMsg received");
|
||||
self.prepare_to_exit(response_chan);
|
||||
return false
|
||||
}
|
||||
ExitNowMsg => {
|
||||
debug!("layout: ExitNowMsg received");
|
||||
|
@ -312,15 +314,21 @@ impl LayoutTask {
|
|||
/// response channel.
|
||||
fn prepare_to_exit(&mut self, response_chan: Chan<()>) {
|
||||
response_chan.send(());
|
||||
loop {
|
||||
match self.port.recv() {
|
||||
ReapLayoutDataMsg(dead_layout_data) => {
|
||||
unsafe {
|
||||
self.handle_reap_layout_data(dead_layout_data)
|
||||
}
|
||||
}
|
||||
ExitNowMsg => self.exit_now(),
|
||||
ExitNowMsg => {
|
||||
self.exit_now();
|
||||
break
|
||||
}
|
||||
_ => {
|
||||
fail!("layout: message that wasn't `ExitNowMsg` received after `PrepareToExitMsg`")
|
||||
fail!("layout: message that wasn't `ExitNowMsg` received after \
|
||||
`PrepareToExitMsg`")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,23 +2,22 @@
|
|||
* 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 extra::url::Url;
|
||||
use compositing::CompositorChan;
|
||||
use gfx::render_task::{RenderChan, RenderTask};
|
||||
use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
|
||||
use gfx::opts::Opts;
|
||||
use layout::layout_task::LayoutTask;
|
||||
|
||||
use extra::url::Url;
|
||||
use gfx::opts::Opts;
|
||||
use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
|
||||
use gfx::render_task::{RenderChan, RenderTask};
|
||||
use script::dom::node::AbstractNode;
|
||||
use script::layout_interface::LayoutChan;
|
||||
use script::script_task::LoadMsg;
|
||||
use servo_msg::constellation_msg::{ConstellationChan, FailureMsg, PipelineId, SubpageId};
|
||||
use script::dom::node::AbstractNode;
|
||||
use script::script_task::{AttachLayoutMsg, NewLayoutInfo, ScriptTask, ScriptChan};
|
||||
use script::script_task;
|
||||
use servo_msg::constellation_msg::{ConstellationChan, FailureMsg, PipelineId, SubpageId};
|
||||
use servo_net::image_cache_task::ImageCacheTask;
|
||||
use servo_net::resource_task::ResourceTask;
|
||||
use servo_util::time::ProfilerChan;
|
||||
use geom::size::Size2D;
|
||||
use extra::future::Future;
|
||||
use std::task;
|
||||
|
||||
/// A uniquely-identifiable pipeline of script task, layout task, and render task.
|
||||
|
@ -34,7 +33,8 @@ pub struct Pipeline {
|
|||
}
|
||||
|
||||
impl Pipeline {
|
||||
/// Starts a render task, layout task, and script task. Returns the channels wrapped in a struct.
|
||||
/// Starts a render task, layout task, and script task. Returns the channels wrapped in a
|
||||
/// struct.
|
||||
pub fn with_script(id: PipelineId,
|
||||
subpage_id: Option<SubpageId>,
|
||||
constellation_chan: ConstellationChan,
|
||||
|
@ -42,8 +42,8 @@ impl Pipeline {
|
|||
image_cache_task: ImageCacheTask,
|
||||
profiler_chan: ProfilerChan,
|
||||
opts: Opts,
|
||||
script_pipeline: &Pipeline,
|
||||
size_future: Future<Size2D<uint>>) -> Pipeline {
|
||||
script_pipeline: &Pipeline)
|
||||
-> Pipeline {
|
||||
let (layout_port, layout_chan) = special_stream!(LayoutChan);
|
||||
let (render_port, render_chan) = special_stream!(RenderChan);
|
||||
|
||||
|
@ -67,7 +67,6 @@ impl Pipeline {
|
|||
old_id: script_pipeline.id.clone(),
|
||||
new_id: id,
|
||||
layout_chan: layout_chan.clone(),
|
||||
size_future: size_future,
|
||||
};
|
||||
|
||||
script_pipeline.script_chan.send(AttachLayoutMsg(new_layout_info));
|
||||
|
@ -86,9 +85,8 @@ impl Pipeline {
|
|||
image_cache_task: ImageCacheTask,
|
||||
resource_task: ResourceTask,
|
||||
profiler_chan: ProfilerChan,
|
||||
opts: Opts,
|
||||
size: Future<Size2D<uint>>) -> Pipeline {
|
||||
|
||||
opts: Opts)
|
||||
-> Pipeline {
|
||||
let (script_port, script_chan) = special_stream!(ScriptChan);
|
||||
let (layout_port, layout_chan) = special_stream!(LayoutChan);
|
||||
let (render_port, render_chan) = special_stream!(RenderChan);
|
||||
|
@ -106,9 +104,15 @@ impl Pipeline {
|
|||
let task_port = supervised_task.future_result();
|
||||
supervised_task.supervised();
|
||||
|
||||
spawn_with!(supervised_task, [script_port, resource_task, size, render_port,
|
||||
layout_port, constellation_chan, image_cache_task,
|
||||
profiler_chan], {
|
||||
spawn_with!(supervised_task, [
|
||||
script_port,
|
||||
resource_task,
|
||||
render_port,
|
||||
layout_port,
|
||||
constellation_chan,
|
||||
image_cache_task,
|
||||
profiler_chan
|
||||
], {
|
||||
ScriptTask::create(id,
|
||||
compositor_chan.clone(),
|
||||
layout_chan.clone(),
|
||||
|
@ -116,8 +120,7 @@ impl Pipeline {
|
|||
script_chan.clone(),
|
||||
constellation_chan.clone(),
|
||||
resource_task,
|
||||
image_cache_task.clone(),
|
||||
size);
|
||||
image_cache_task.clone());
|
||||
|
||||
RenderTask::create(id,
|
||||
render_port,
|
||||
|
@ -187,8 +190,7 @@ impl Pipeline {
|
|||
}
|
||||
|
||||
pub fn exit(&self) {
|
||||
// Script task handles shutting down layout,
|
||||
// and layout handles shutting down the renderer.
|
||||
// Script task handles shutting down layout, and layout handles shutting down the renderer.
|
||||
self.script_chan.try_send(script_task::ExitPipelineMsg(self.id));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ extern mod core_text = "rust-core-text";
|
|||
|
||||
use compositing::{CompositorChan, CompositorTask};
|
||||
use constellation::Constellation;
|
||||
use servo_msg::constellation_msg::{ExitMsg, InitLoadUrlMsg};
|
||||
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, InitLoadUrlMsg};
|
||||
|
||||
#[cfg(not(test))]
|
||||
use gfx::opts;
|
||||
|
@ -127,17 +127,28 @@ fn run(opts: Opts) {
|
|||
let (shutdown_port, shutdown_chan) = comm::stream();
|
||||
let (profiler_port, profiler_chan) = special_stream!(ProfilerChan);
|
||||
let (compositor_port, compositor_chan) = special_stream!(CompositorChan);
|
||||
let (constellation_port, constellation_chan) = special_stream!(ConstellationChan);
|
||||
|
||||
Profiler::create(profiler_port, profiler_chan.clone(), opts.profiler_period);
|
||||
|
||||
do spawn_with((profiler_chan.clone(), compositor_chan, opts.clone()))
|
||||
|(profiler_chan, compositor_chan, opts)| {
|
||||
|
||||
do spawn_with((constellation_port,
|
||||
constellation_chan.clone(),
|
||||
profiler_chan.clone(),
|
||||
compositor_chan,
|
||||
opts.clone()))
|
||||
|(constellation_port,
|
||||
constellation_chan,
|
||||
profiler_chan,
|
||||
compositor_chan,
|
||||
opts)| {
|
||||
let opts = &opts;
|
||||
|
||||
// Create a Servo instance.
|
||||
let resource_task = ResourceTask();
|
||||
let image_cache_task = ImageCacheTask(resource_task.clone());
|
||||
let constellation_chan = Constellation::start(compositor_chan,
|
||||
Constellation::start(constellation_port,
|
||||
constellation_chan.clone(),
|
||||
compositor_chan,
|
||||
opts,
|
||||
resource_task,
|
||||
image_cache_task,
|
||||
|
@ -158,11 +169,12 @@ fn run(opts: Opts) {
|
|||
exit_response_from_constellation.recv();
|
||||
}
|
||||
|
||||
|
||||
let compositor_task = CompositorTask::new(opts,
|
||||
compositor_port,
|
||||
constellation_chan,
|
||||
profiler_chan,
|
||||
shutdown_chan);
|
||||
|
||||
debug!("preparing to enter main loop");
|
||||
compositor_task.run();
|
||||
}
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
//! The high-level interface from script to constellation. Using this abstract interface helps reduce
|
||||
/// coupling between these two components
|
||||
|
||||
use std::comm::{Chan, SharedChan};
|
||||
use extra::url::Url;
|
||||
use extra::future::Future;
|
||||
use geom::size::Size2D;
|
||||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
use std::comm::{Chan, SharedChan};
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct ConstellationChan(SharedChan<Msg>);
|
||||
|
@ -32,8 +31,8 @@ pub enum Msg {
|
|||
FailureMsg(PipelineId, Option<SubpageId>),
|
||||
InitLoadUrlMsg(Url),
|
||||
FrameRectMsg(PipelineId, SubpageId, Rect<f32>),
|
||||
LoadUrlMsg(PipelineId, Url, Future<Size2D<uint>>),
|
||||
LoadIframeUrlMsg(Url, PipelineId, SubpageId, Future<Size2D<uint>>, IFrameSandboxState),
|
||||
LoadUrlMsg(PipelineId, Url),
|
||||
LoadIframeUrlMsg(Url, PipelineId, SubpageId, IFrameSandboxState),
|
||||
NavigateMsg(NavigationDirection),
|
||||
RendererReadyMsg(PipelineId),
|
||||
ResizedWindowMsg(Size2D<uint>),
|
||||
|
|
|
@ -9,15 +9,11 @@ use dom::element::HTMLIframeElementTypeId;
|
|||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{AbstractNode, Node, ScriptView};
|
||||
use dom::windowproxy::WindowProxy;
|
||||
use geom::size::Size2D;
|
||||
use geom::rect::Rect;
|
||||
|
||||
use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg, PipelineId, SubpageId};
|
||||
|
||||
use std::ascii::StrAsciiExt;
|
||||
use std::comm::ChanOne;
|
||||
use extra::url::Url;
|
||||
use std::util::replace;
|
||||
use geom::rect::Rect;
|
||||
use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg, PipelineId, SubpageId};
|
||||
use std::ascii::StrAsciiExt;
|
||||
|
||||
enum SandboxAllowance {
|
||||
AllowNothing = 0x00,
|
||||
|
@ -39,17 +35,11 @@ pub struct HTMLIFrameElement {
|
|||
struct IFrameSize {
|
||||
pipeline_id: PipelineId,
|
||||
subpage_id: SubpageId,
|
||||
future_chan: Option<ChanOne<Size2D<uint>>>,
|
||||
constellation_chan: ConstellationChan,
|
||||
}
|
||||
|
||||
impl IFrameSize {
|
||||
pub fn set_rect(&mut self, rect: Rect<f32>) {
|
||||
let future_chan = replace(&mut self.future_chan, None);
|
||||
do future_chan.map |future_chan| {
|
||||
let Size2D { width, height } = rect.size;
|
||||
future_chan.send(Size2D(width as uint, height as uint));
|
||||
};
|
||||
self.constellation_chan.send(FrameRectMsg(self.pipeline_id, self.subpage_id, rect));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,26 +12,24 @@ use dom::namespace;
|
|||
use dom::node::{AbstractNode, ElementNodeTypeId, ScriptView};
|
||||
use dom::types::*;
|
||||
use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
|
||||
use js::jsapi::JSContext;
|
||||
use style::Stylesheet;
|
||||
use script_task::page_from_context;
|
||||
|
||||
use std::cast;
|
||||
use std::cell::Cell;
|
||||
use std::comm;
|
||||
use std::comm::{Port, SharedChan};
|
||||
use std::str;
|
||||
use std::str::eq_slice;
|
||||
use std::from_str::FromStr;
|
||||
use extra::url::Url;
|
||||
use hubbub::hubbub;
|
||||
use js::jsapi::JSContext;
|
||||
use servo_msg::constellation_msg::{ConstellationChan, SubpageId};
|
||||
use servo_net::image_cache_task::ImageCacheTask;
|
||||
use servo_net::resource_task::{Load, Payload, Done, ResourceTask, load_whole_resource};
|
||||
use servo_util::tree::{TreeNodeRef, ElementLike};
|
||||
use servo_util::url::make_url;
|
||||
use extra::future::Future;
|
||||
use extra::url::Url;
|
||||
use geom::size::Size2D;
|
||||
use std::cast;
|
||||
use std::cell::Cell;
|
||||
use std::comm::{Port, SharedChan};
|
||||
use std::comm;
|
||||
use std::from_str::FromStr;
|
||||
use std::str::eq_slice;
|
||||
use std::str;
|
||||
use style::Stylesheet;
|
||||
|
||||
macro_rules! handle_element(
|
||||
($document: expr,
|
||||
|
@ -67,7 +65,7 @@ enum JSMessage {
|
|||
/// Messages generated by the HTML parser upon discovery of additional resources
|
||||
pub enum HtmlDiscoveryMessage {
|
||||
HtmlDiscoveredStyle(Stylesheet),
|
||||
HtmlDiscoveredIFrame((Url, SubpageId, Future<Size2D<uint>>, bool)),
|
||||
HtmlDiscoveredIFrame((Url, SubpageId, bool)),
|
||||
HtmlDiscoveredScript(JSResult)
|
||||
}
|
||||
|
||||
|
@ -374,10 +372,6 @@ pub fn parse_html(cx: *JSContext,
|
|||
let iframe_url = make_url(src.clone(), Some(url2.clone()));
|
||||
iframe_element.frame = Some(iframe_url.clone());
|
||||
|
||||
// Size future
|
||||
let (port, chan) = comm::oneshot();
|
||||
let size_future = Future::from_port(port);
|
||||
|
||||
// Subpage Id
|
||||
let subpage_id = next_subpage_id.take();
|
||||
next_subpage_id.put_back(SubpageId(*subpage_id + 1));
|
||||
|
@ -391,11 +385,11 @@ pub fn parse_html(cx: *JSContext,
|
|||
iframe_element.size = Some(IFrameSize {
|
||||
pipeline_id: pipeline_id,
|
||||
subpage_id: subpage_id,
|
||||
future_chan: Some(chan),
|
||||
constellation_chan: constellation_chan.clone(),
|
||||
});
|
||||
iframe_chan.send(HtmlDiscoveredIFrame((iframe_url, subpage_id,
|
||||
size_future, sandboxed)));
|
||||
iframe_chan.send(HtmlDiscoveredIFrame((iframe_url,
|
||||
subpage_id,
|
||||
sandboxed)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,11 +27,9 @@ use layout_interface::ContentChangedDocumentDamage;
|
|||
use layout_interface;
|
||||
|
||||
use dom::node::ScriptView;
|
||||
use extra::future::Future;
|
||||
use extra::url::Url;
|
||||
use std::str::eq_slice;
|
||||
use geom::size::Size2D;
|
||||
use geom::point::Point2D;
|
||||
use geom::size::Size2D;
|
||||
use js::JSVAL_NULL;
|
||||
use js::global::debug_fns;
|
||||
use js::glue::RUST_JSVAL_TO_OBJECT;
|
||||
|
@ -53,6 +51,7 @@ use std::cell::Cell;
|
|||
use std::comm::{Port, SharedChan};
|
||||
use std::comm;
|
||||
use std::ptr;
|
||||
use std::str::eq_slice;
|
||||
use std::task::{spawn_sched, SingleThreaded};
|
||||
use std::util::replace;
|
||||
|
||||
|
@ -84,7 +83,6 @@ pub struct NewLayoutInfo {
|
|||
old_id: PipelineId,
|
||||
new_id: PipelineId,
|
||||
layout_chan: LayoutChan,
|
||||
size_future: Future<Size2D<uint>>,
|
||||
}
|
||||
|
||||
/// Encapsulates external communication with the script task.
|
||||
|
@ -118,8 +116,8 @@ pub struct Page {
|
|||
/// What parts of the document are dirty, if any.
|
||||
damage: Option<DocumentDamage>,
|
||||
|
||||
/// The current size of the window, in pixels.
|
||||
window_size: Future<Size2D<uint>>,
|
||||
/// The current size of the window, in pixels. If `None`, we do not know the window size yet.
|
||||
window_size: Option<Size2D<uint>>,
|
||||
|
||||
js_info: Option<JSPageInfo>,
|
||||
|
||||
|
@ -148,7 +146,7 @@ pub struct PageTreeIterator<'self> {
|
|||
}
|
||||
|
||||
impl PageTree {
|
||||
fn new(id: PipelineId, layout_chan: LayoutChan, size_future: Future<Size2D<uint>>) -> PageTree {
|
||||
fn new(id: PipelineId, layout_chan: LayoutChan) -> PageTree {
|
||||
PageTree {
|
||||
page: @mut Page {
|
||||
id: id,
|
||||
|
@ -156,7 +154,7 @@ impl PageTree {
|
|||
layout_chan: layout_chan,
|
||||
layout_join_port: None,
|
||||
damage: None,
|
||||
window_size: size_future,
|
||||
window_size: None,
|
||||
js_info: None,
|
||||
url: None,
|
||||
next_subpage_id: SubpageId(0),
|
||||
|
@ -280,18 +278,32 @@ impl Page {
|
|||
response_port.recv()
|
||||
}
|
||||
|
||||
/// This method will wait until the layout task has completed its current action, join the
|
||||
/// layout task, and then request a new layout run. It won't wait for the new layout
|
||||
/// computation to finish.
|
||||
/// Reflows the page if it's possible to do so. This method will wait until the layout task has
|
||||
/// completed its current action, join the layout task, and then request a new layout run. It
|
||||
/// won't wait for the new layout computation to finish.
|
||||
///
|
||||
/// If there is no window size yet, the page is presumed invisible and no reflow is performed.
|
||||
///
|
||||
/// This function fails if there is no root frame.
|
||||
pub fn reflow(&mut self, goal: ReflowGoal, script_chan: ScriptChan, compositor: @ScriptListener) {
|
||||
pub fn reflow(&mut self,
|
||||
goal: ReflowGoal,
|
||||
script_chan: ScriptChan,
|
||||
compositor: @ScriptListener) {
|
||||
let root = match self.frame {
|
||||
None => return,
|
||||
Some(ref frame) => {
|
||||
frame.document.document().GetDocumentElement()
|
||||
}
|
||||
};
|
||||
|
||||
let window_size = match self.window_size {
|
||||
None => {
|
||||
debug!("not reflowing due to lack of a window size");
|
||||
return
|
||||
}
|
||||
Some(window_size) => window_size,
|
||||
};
|
||||
|
||||
match root {
|
||||
None => {},
|
||||
Some(root) => {
|
||||
|
@ -314,7 +326,7 @@ impl Page {
|
|||
document_root: root,
|
||||
url: self.url.get_ref().first().clone(),
|
||||
goal: goal,
|
||||
window_size: self.window_size.get(),
|
||||
window_size: window_size,
|
||||
script_chan: script_chan,
|
||||
script_join_chan: join_chan,
|
||||
damage: replace(&mut self.damage, None).unwrap(),
|
||||
|
@ -329,8 +341,8 @@ impl Page {
|
|||
}
|
||||
|
||||
pub fn initialize_js_info(&mut self, js_context: @Cx, global: *JSObject) {
|
||||
// Note that the order that these variables are initialized is _not_ arbitrary. Switching them around
|
||||
// can -- and likely will -- lead to things breaking.
|
||||
// Note that the order that these variables are initialized is _not_ arbitrary. Switching
|
||||
// them around can -- and likely will -- lead to things breaking.
|
||||
|
||||
js_context.set_default_options_and_version();
|
||||
js_context.set_logging_error_reporter();
|
||||
|
@ -425,13 +437,12 @@ impl ScriptTask {
|
|||
chan: ScriptChan,
|
||||
constellation_chan: ConstellationChan,
|
||||
resource_task: ResourceTask,
|
||||
img_cache_task: ImageCacheTask,
|
||||
initial_size: Future<Size2D<uint>>)
|
||||
img_cache_task: ImageCacheTask)
|
||||
-> @mut ScriptTask {
|
||||
let js_runtime = js::rust::rt();
|
||||
|
||||
let script_task = @mut ScriptTask {
|
||||
page_tree: PageTree::new(id, layout_chan, initial_size),
|
||||
page_tree: PageTree::new(id, layout_chan),
|
||||
|
||||
image_cache_task: img_cache_task,
|
||||
resource_task: resource_task,
|
||||
|
@ -463,16 +474,25 @@ impl ScriptTask {
|
|||
chan: ScriptChan,
|
||||
constellation_chan: ConstellationChan,
|
||||
resource_task: ResourceTask,
|
||||
image_cache_task: ImageCacheTask,
|
||||
initial_size: Future<Size2D<uint>>) {
|
||||
let parms = Cell::new((compositor, layout_chan, port, chan, constellation_chan,
|
||||
resource_task, image_cache_task, initial_size));
|
||||
image_cache_task: ImageCacheTask) {
|
||||
let parms = Cell::new((compositor,
|
||||
layout_chan,
|
||||
port,
|
||||
chan,
|
||||
constellation_chan,
|
||||
resource_task,
|
||||
image_cache_task));
|
||||
// Since SpiderMonkey is blocking it needs to run in its own thread.
|
||||
// If we don't do this then we'll just end up with a bunch of SpiderMonkeys
|
||||
// starving all the other tasks.
|
||||
do spawn_sched(SingleThreaded) {
|
||||
let (compositor, layout_chan, port, chan, constellation_chan,
|
||||
resource_task, image_cache_task, initial_size) = parms.take();
|
||||
let (compositor,
|
||||
layout_chan,
|
||||
port,
|
||||
chan,
|
||||
constellation_chan,
|
||||
resource_task,
|
||||
image_cache_task) = parms.take();
|
||||
let script_task = ScriptTask::new(id,
|
||||
@compositor as @ScriptListener,
|
||||
layout_chan,
|
||||
|
@ -480,8 +500,7 @@ impl ScriptTask {
|
|||
chan,
|
||||
constellation_chan,
|
||||
resource_task,
|
||||
image_cache_task,
|
||||
initial_size);
|
||||
image_cache_task);
|
||||
script_task.start();
|
||||
}
|
||||
}
|
||||
|
@ -512,6 +531,7 @@ impl ScriptTask {
|
|||
let event = self.port.recv();
|
||||
match event {
|
||||
ResizeMsg(id, size) => {
|
||||
debug!("script got resize message");
|
||||
let page = self.page_tree.find(id).expect("resize sent to nonexistent pipeline").page;
|
||||
page.resize_event = Some(size);
|
||||
}
|
||||
|
@ -538,7 +558,10 @@ impl ScriptTask {
|
|||
ReflowCompleteMsg(id, reflow_id) => self.handle_reflow_complete_msg(id, reflow_id),
|
||||
ResizeInactiveMsg(id, new_size) => self.handle_resize_inactive_msg(id, new_size),
|
||||
ExitPipelineMsg(id) => if self.handle_exit_pipeline_msg(id) { return false },
|
||||
ExitWindowMsg(id) => if self.handle_exit_window_msg(id) { return false },
|
||||
ExitWindowMsg(id) => {
|
||||
self.handle_exit_window_msg(id);
|
||||
return false
|
||||
},
|
||||
ResizeMsg(*) => fail!("should have handled ResizeMsg already"),
|
||||
}
|
||||
}
|
||||
|
@ -551,14 +574,13 @@ impl ScriptTask {
|
|||
let NewLayoutInfo {
|
||||
old_id,
|
||||
new_id,
|
||||
layout_chan,
|
||||
size_future
|
||||
layout_chan
|
||||
} = new_layout_info;
|
||||
|
||||
let parent_page_tree = self.page_tree.find(old_id).expect("ScriptTask: received a layout
|
||||
whose parent has a PipelineId which does not correspond to a pipeline in the script
|
||||
task's page tree. This is a bug.");
|
||||
let new_page_tree = PageTree::new(new_id, layout_chan, size_future);
|
||||
let new_page_tree = PageTree::new(new_id, layout_chan);
|
||||
parent_page_tree.inner.push(new_page_tree);
|
||||
}
|
||||
|
||||
|
@ -612,30 +634,30 @@ impl ScriptTask {
|
|||
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 = Future::from_value(new_size);
|
||||
page.window_size = Some(new_size);
|
||||
let last_loaded_url = replace(&mut page.url, None);
|
||||
for url in last_loaded_url.iter() {
|
||||
page.url = Some((url.first(), true));
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_exit_window_msg(&mut self, id: PipelineId) -> bool {
|
||||
fn handle_exit_window_msg(&mut self, id: PipelineId) {
|
||||
debug!("script task handling exit window msg");
|
||||
self.handle_exit_pipeline_msg(id);
|
||||
|
||||
// TODO(tkuehn): currently there is only one window,
|
||||
// so this can afford to be naive and just shut down the
|
||||
// compositor. In the future it'll need to be smarter.
|
||||
self.compositor.close();
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
/// Handles a request to exit the script task and shut down layout.
|
||||
/// Returns true if the script task should shut down and false otherwise.
|
||||
fn handle_exit_pipeline_msg(&mut self, id: PipelineId) -> bool {
|
||||
// If root is being exited, shut down all pages
|
||||
if self.page_tree.page.id == id {
|
||||
for page in self.page_tree.iter() {
|
||||
debug!("shutting down layout for root page {:?}", page.id);
|
||||
shut_down_layout(page)
|
||||
}
|
||||
return true
|
||||
|
@ -645,6 +667,7 @@ impl ScriptTask {
|
|||
match self.page_tree.remove(id) {
|
||||
Some(ref mut page_tree) => {
|
||||
for page in page_tree.iter() {
|
||||
debug!("shutting down layout for page {:?}", page.id);
|
||||
shut_down_layout(page)
|
||||
}
|
||||
false
|
||||
|
@ -727,7 +750,7 @@ impl ScriptTask {
|
|||
Some(HtmlDiscoveredStyle(sheet)) => {
|
||||
page.layout_chan.send(AddStylesheetMsg(sheet));
|
||||
}
|
||||
Some(HtmlDiscoveredIFrame((iframe_url, subpage_id, size_future, sandboxed))) => {
|
||||
Some(HtmlDiscoveredIFrame((iframe_url, subpage_id, sandboxed))) => {
|
||||
page.next_subpage_id = SubpageId(*subpage_id + 1);
|
||||
let sandboxed = if sandboxed {
|
||||
IFrameSandboxed
|
||||
|
@ -737,7 +760,6 @@ impl ScriptTask {
|
|||
self.constellation_chan.send(LoadIframeUrlMsg(iframe_url,
|
||||
pipeline_id,
|
||||
subpage_id,
|
||||
size_future,
|
||||
sandboxed));
|
||||
}
|
||||
None => break
|
||||
|
@ -824,7 +846,7 @@ impl ScriptTask {
|
|||
ResizeEvent(new_width, new_height) => {
|
||||
debug!("script got resize event: {:u}, {:u}", new_width, new_height);
|
||||
|
||||
page.window_size = Future::from_value(Size2D(new_width, new_height));
|
||||
page.window_size = Some(Size2D(new_width, new_height));
|
||||
|
||||
if page.frame.is_some() {
|
||||
page.damage(ReflowDocumentDamage);
|
||||
|
@ -906,7 +928,7 @@ impl ScriptTask {
|
|||
None => {}
|
||||
}
|
||||
} else {
|
||||
self.constellation_chan.send(LoadUrlMsg(page.id, url, Future::from_value(page.window_size.get())));
|
||||
self.constellation_chan.send(LoadUrlMsg(page.id, url));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div></div>
|
||||
<div class="frame">
|
||||
<iframe id="frameone" sandbox="allow-scripts" src="summit-two.html">
|
||||
</iframe>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue