aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/compositing/compositing.rs2
-rw-r--r--src/components/compositing/constellation.rs52
-rw-r--r--src/components/compositing/events.rs8
-rw-r--r--src/components/compositing/pipeline.rs64
-rw-r--r--src/components/layout/layout.rs1
-rw-r--r--src/components/layout/layout_task.rs79
-rw-r--r--src/components/layout_traits/layout_traits.rs21
-rw-r--r--src/components/main/servo.rs3
-rw-r--r--src/components/script/dom/event.rs12
-rw-r--r--src/components/script/dom/window.rs6
-rw-r--r--src/components/script/layout_interface.rs31
-rw-r--r--src/components/script/page.rs4
-rw-r--r--src/components/script/script.rs1
-rw-r--r--src/components/script/script_task.rs203
-rw-r--r--src/components/script_traits/script_traits.rs98
15 files changed, 396 insertions, 189 deletions
diff --git a/src/components/compositing/compositing.rs b/src/components/compositing/compositing.rs
index c03cc7ca3e0..ef3875fc58d 100644
--- a/src/components/compositing/compositing.rs
+++ b/src/components/compositing/compositing.rs
@@ -27,7 +27,7 @@ extern crate layers;
extern crate layout_traits;
extern crate opengles;
extern crate png;
-extern crate script;
+extern crate script_traits;
extern crate servo_msg = "msg";
extern crate servo_net = "net";
#[phase(plugin, link)]
diff --git a/src/components/compositing/constellation.rs b/src/components/compositing/constellation.rs
index 31030f8a0c2..179327d9962 100644
--- a/src/components/compositing/constellation.rs
+++ b/src/components/compositing/constellation.rs
@@ -10,11 +10,9 @@ use geom::size::TypedSize2D;
use gfx::render_task;
use libc;
use pipeline::{Pipeline, CompositionPipeline};
-use layout_traits::LayoutTaskFactory;
-use script::script_task::{ResizeMsg, ResizeInactiveMsg, ExitPipelineMsg};
-use script::layout_interface;
-use script::layout_interface::LayoutChan;
-use script::script_task::ScriptChan;
+use layout_traits::{LayoutControlChan, LayoutTaskFactory, ExitNowMsg};
+use script_traits::{ResizeMsg, ResizeInactiveMsg, ExitPipelineMsg};
+use script_traits::{ScriptControlChan, ScriptTaskFactory};
use servo_msg::compositor_msg::LayerId;
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, Failure, FrameRectMsg};
use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
@@ -37,7 +35,7 @@ use std::rc::Rc;
use url::Url;
/// Maintains the pipelines and navigation context and grants permission to composite
-pub struct Constellation<LTF> {
+pub struct Constellation<LTF, STF> {
pub chan: ConstellationChan,
pub request_port: Receiver<Msg>,
pub compositor_chan: CompositorChan,
@@ -240,7 +238,7 @@ impl NavigationContext {
}
}
-impl<LTF: LayoutTaskFactory> Constellation<LTF> {
+impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
pub fn start(compositor_chan: CompositorChan,
opts: &Opts,
resource_task: ResourceTask,
@@ -252,7 +250,7 @@ impl<LTF: LayoutTaskFactory> Constellation<LTF> {
let constellation_chan_clone = constellation_chan.clone();
let opts_clone = opts.clone();
spawn_named("Constellation", proc() {
- let mut constellation : Constellation<LTF> = Constellation {
+ let mut constellation : Constellation<LTF, STF> = Constellation {
chan: constellation_chan_clone,
request_port: constellation_port,
compositor_chan: compositor_chan,
@@ -293,18 +291,18 @@ impl<LTF: LayoutTaskFactory> Constellation<LTF> {
script_pipeline: Option<Rc<Pipeline>>,
url: Url)
-> Rc<Pipeline> {
- let pipe = Pipeline::create::<LTF>(id,
- subpage_id,
- self.chan.clone(),
- self.compositor_chan.clone(),
- self.image_cache_task.clone(),
- self.font_cache_task.clone(),
- self.resource_task.clone(),
- self.time_profiler_chan.clone(),
- self.window_size,
- self.opts.clone(),
- script_pipeline,
- url);
+ let pipe = Pipeline::create::<LTF, STF>(id,
+ subpage_id,
+ self.chan.clone(),
+ self.compositor_chan.clone(),
+ self.image_cache_task.clone(),
+ self.font_cache_task.clone(),
+ self.resource_task.clone(),
+ self.time_profiler_chan.clone(),
+ self.window_size,
+ self.opts.clone(),
+ script_pipeline,
+ url);
pipe.load();
Rc::new(pipe)
}
@@ -421,11 +419,11 @@ impl<LTF: LayoutTaskFactory> Constellation<LTF> {
};
fn force_pipeline_exit(old_pipeline: &Rc<Pipeline>) {
- let ScriptChan(ref old_script) = old_pipeline.script_chan;
+ let ScriptControlChan(ref old_script) = old_pipeline.script_chan;
let _ = old_script.send_opt(ExitPipelineMsg(old_pipeline.id));
let _ = old_pipeline.render_chan.send_opt(render_task::ExitMsg(None));
- let LayoutChan(ref old_layout) = old_pipeline.layout_chan;
- let _ = old_layout.send_opt(layout_interface::ExitNowMsg);
+ let LayoutControlChan(ref old_layout) = old_pipeline.layout_chan;
+ let _ = old_layout.send_opt(ExitNowMsg);
}
force_pipeline_exit(&old_pipeline);
self.pipelines.remove(&pipeline_id);
@@ -503,7 +501,7 @@ impl<LTF: LayoutTaskFactory> Constellation<LTF> {
let pipeline = &child_frame_tree.frame_tree.pipeline;
if !already_sent.contains(&pipeline.id) {
if is_active {
- let ScriptChan(ref script_chan) = pipeline.script_chan;
+ let ScriptControlChan(ref script_chan) = pipeline.script_chan;
script_chan.send(ResizeMsg(pipeline.id, WindowSizeData {
visible_viewport: rect.size,
initial_viewport: rect.size * ScaleFactor(1.0),
@@ -783,7 +781,7 @@ impl<LTF: LayoutTaskFactory> Constellation<LTF> {
for frame_tree in self.current_frame().iter() {
debug!("constellation sending resize message to active frame");
let pipeline = &frame_tree.pipeline;
- let ScriptChan(ref chan) = pipeline.script_chan;
+ let ScriptControlChan(ref chan) = pipeline.script_chan;
let _ = chan.send_opt(ResizeMsg(pipeline.id, new_size));
already_seen.insert(pipeline.id);
}
@@ -792,7 +790,7 @@ impl<LTF: LayoutTaskFactory> Constellation<LTF> {
let pipeline = &frame_tree.pipeline;
if !already_seen.contains(&pipeline.id) {
debug!("constellation sending resize message to inactive frame");
- let ScriptChan(ref chan) = pipeline.script_chan;
+ let ScriptControlChan(ref chan) = pipeline.script_chan;
let _ = chan.send_opt(ResizeInactiveMsg(pipeline.id, new_size));
already_seen.insert(pipeline.id);
}
@@ -805,7 +803,7 @@ impl<LTF: LayoutTaskFactory> Constellation<LTF> {
if frame_tree.parent.borrow().is_none() {
debug!("constellation sending resize message to pending outer frame ({:?})",
frame_tree.pipeline.id);
- let ScriptChan(ref chan) = frame_tree.pipeline.script_chan;
+ let ScriptControlChan(ref chan) = frame_tree.pipeline.script_chan;
let _ = chan.send_opt(ResizeMsg(frame_tree.pipeline.id, new_size));
}
}
diff --git a/src/components/compositing/events.rs b/src/components/compositing/events.rs
index e4f57a3bb15..4699208eed2 100644
--- a/src/components/compositing/events.rs
+++ b/src/components/compositing/events.rs
@@ -11,8 +11,8 @@ use geom::rect::{Rect, TypedRect};
use geom::scale_factor::ScaleFactor;
use geom::size::{Size2D, TypedSize2D};
use layers::layers::Layer;
-use script::dom::event::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
-use script::script_task::{ScriptChan, SendEventMsg};
+use script_traits::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent, SendEventMsg};
+use script_traits::{ScriptControlChan};
use servo_msg::compositor_msg::{FixedPosition, LayerId};
use servo_msg::constellation_msg::PipelineId;
use servo_util::geometry::{DevicePixel, PagePx};
@@ -139,14 +139,14 @@ pub fn send_mouse_event(layer: Rc<Layer<CompositorData>>,
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, cursor.to_untyped()),
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, cursor.to_untyped()),
};
- let ScriptChan(ref chan) = layer.extra_data.borrow().pipeline.script_chan;
+ let ScriptControlChan(ref chan) = layer.extra_data.borrow().pipeline.script_chan;
let _ = chan.send_opt(SendEventMsg(layer.extra_data.borrow().pipeline.id.clone(), message));
}
pub fn send_mouse_move_event(layer: Rc<Layer<CompositorData>>,
cursor: TypedPoint2D<PagePx, f32>) {
let message = MouseMoveEvent(cursor.to_untyped());
- let ScriptChan(ref chan) = layer.extra_data.borrow().pipeline.script_chan;
+ let ScriptControlChan(ref chan) = layer.extra_data.borrow().pipeline.script_chan;
let _ = chan.send_opt(SendEventMsg(layer.extra_data.borrow().pipeline.id.clone(), message));
}
diff --git a/src/components/compositing/pipeline.rs b/src/components/compositing/pipeline.rs
index 2c2a4e5e394..8ccc0fe48a5 100644
--- a/src/components/compositing/pipeline.rs
+++ b/src/components/compositing/pipeline.rs
@@ -3,14 +3,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use CompositorChan;
-use layout_traits::LayoutTaskFactory;
+use layout_traits::{LayoutTaskFactory, LayoutControlChan};
+use script_traits::{ScriptControlChan, ScriptTaskFactory};
+use script_traits::{AttachLayoutMsg, LoadMsg, NewLayoutInfo, ExitPipelineMsg};
use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
use gfx::render_task::{RenderChan, RenderTask};
-use script::layout_interface::LayoutChan;
-use script::script_task::LoadMsg;
-use script::script_task::{AttachLayoutMsg, NewLayoutInfo, ScriptTask, ScriptChan};
-use script::script_task;
use servo_msg::constellation_msg::{ConstellationChan, Failure, PipelineId, SubpageId};
use servo_msg::constellation_msg::WindowSizeData;
use servo_net::image_cache_task::ImageCacheTask;
@@ -25,8 +23,8 @@ use url::Url;
pub struct Pipeline {
pub id: PipelineId,
pub subpage_id: Option<SubpageId>,
- pub script_chan: ScriptChan,
- pub layout_chan: LayoutChan,
+ pub script_chan: ScriptControlChan,
+ pub layout_chan: LayoutControlChan,
pub render_chan: RenderChan,
pub layout_shutdown_port: Receiver<()>,
pub render_shutdown_port: Receiver<()>,
@@ -38,7 +36,7 @@ pub struct Pipeline {
#[deriving(Clone)]
pub struct CompositionPipeline {
pub id: PipelineId,
- pub script_chan: ScriptChan,
+ pub script_chan: ScriptControlChan,
pub render_chan: RenderChan,
}
@@ -46,7 +44,7 @@ impl Pipeline {
/// Starts a render task, layout task, and possibly a script task.
/// Returns the channels wrapped in a struct.
/// If script_pipeline is not None, then subpage_id must also be not None.
- pub fn create<LTF:LayoutTaskFactory>(
+ pub fn create<LTF:LayoutTaskFactory, STF:ScriptTaskFactory>(
id: PipelineId,
subpage_id: Option<SubpageId>,
constellation_chan: ConstellationChan,
@@ -60,10 +58,11 @@ impl Pipeline {
script_pipeline: Option<Rc<Pipeline>>,
url: Url)
-> Pipeline {
- let (layout_port, layout_chan) = LayoutChan::new();
+ let layout_pair = ScriptTaskFactory::create_layout_channel(None::<&mut STF>);
let (render_port, render_chan) = RenderChan::new();
let (render_shutdown_chan, render_shutdown_port) = channel();
let (layout_shutdown_chan, layout_shutdown_port) = channel();
+ let (pipeline_chan, pipeline_port) = channel();
let failure = Failure {
pipeline_id: id,
@@ -72,28 +71,29 @@ impl Pipeline {
let script_chan = match script_pipeline {
None => {
- let (script_port, script_chan) = ScriptChan::new();
- ScriptTask::create(id,
- box compositor_chan.clone(),
- layout_chan.clone(),
- script_port,
- script_chan.clone(),
- constellation_chan.clone(),
- failure.clone(),
- resource_task,
- image_cache_task.clone(),
- window_size);
- script_chan
+ let (script_chan, script_port) = channel();
+ ScriptTaskFactory::create(None::<&mut STF>,
+ id,
+ box compositor_chan.clone(),
+ &layout_pair,
+ ScriptControlChan(script_chan.clone()),
+ script_port,
+ constellation_chan.clone(),
+ failure.clone(),
+ resource_task,
+ image_cache_task.clone(),
+ window_size);
+ ScriptControlChan(script_chan)
}
Some(spipe) => {
let new_layout_info = NewLayoutInfo {
old_pipeline_id: spipe.id.clone(),
new_pipeline_id: id,
subpage_id: subpage_id.expect("script_pipeline != None but subpage_id == None"),
- layout_chan: layout_chan.clone(),
+ layout_chan: ScriptTaskFactory::clone_layout_channel(None::<&mut STF>, &layout_pair),
};
- let ScriptChan(ref chan) = spipe.script_chan;
+ let ScriptControlChan(ref chan) = spipe.script_chan;
chan.send(AttachLayoutMsg(new_layout_info));
spipe.script_chan.clone()
}
@@ -111,8 +111,8 @@ impl Pipeline {
LayoutTaskFactory::create(None::<&mut LTF>,
id,
- layout_port,
- layout_chan.clone(),
+ layout_pair,
+ pipeline_port,
constellation_chan,
failure,
script_chan.clone(),
@@ -126,7 +126,7 @@ impl Pipeline {
Pipeline::new(id,
subpage_id,
script_chan,
- layout_chan,
+ LayoutControlChan(pipeline_chan),
render_chan,
layout_shutdown_port,
render_shutdown_port,
@@ -135,8 +135,8 @@ impl Pipeline {
pub fn new(id: PipelineId,
subpage_id: Option<SubpageId>,
- script_chan: ScriptChan,
- layout_chan: LayoutChan,
+ script_chan: ScriptControlChan,
+ layout_chan: LayoutControlChan,
render_chan: RenderChan,
layout_shutdown_port: Receiver<()>,
render_shutdown_port: Receiver<()>,
@@ -155,7 +155,7 @@ impl Pipeline {
}
pub fn load(&self) {
- let ScriptChan(ref chan) = self.script_chan;
+ let ScriptControlChan(ref chan) = self.script_chan;
chan.send(LoadMsg(self.id, self.url.clone()));
}
@@ -173,8 +173,8 @@ impl Pipeline {
// Script task handles shutting down layout, and layout handles shutting down the renderer.
// For now, if the script task has failed, we give up on clean shutdown.
- let ScriptChan(ref chan) = self.script_chan;
- if chan.send_opt(script_task::ExitPipelineMsg(self.id)).is_ok() {
+ let ScriptControlChan(ref chan) = self.script_chan;
+ if chan.send_opt(ExitPipelineMsg(self.id)).is_ok() {
// Wait until all slave tasks have terminated and run destructors
// NOTE: We don't wait for script task as we don't always own it
let _ = self.render_shutdown_port.recv_opt();
diff --git a/src/components/layout/layout.rs b/src/components/layout/layout.rs
index 70fba05db5e..65acf09cc31 100644
--- a/src/components/layout/layout.rs
+++ b/src/components/layout/layout.rs
@@ -19,6 +19,7 @@ extern crate geom;
extern crate gfx;
extern crate layout_traits;
extern crate script;
+extern crate script_traits;
extern crate style;
#[phase(plugin)]
extern crate servo_macros = "macros";
diff --git a/src/components/layout/layout_task.rs b/src/components/layout/layout_task.rs
index 8c3fecd3368..e90545ed6d6 100644
--- a/src/components/layout/layout_task.rs
+++ b/src/components/layout/layout_task.rs
@@ -30,18 +30,18 @@ use gfx::display_list::{DisplayItemIterator, DisplayList, OpaqueNode};
use gfx::font_context::FontContext;
use gfx::render_task::{RenderInitMsg, RenderChan, RenderLayer};
use gfx::{render_task, color};
-use layout_traits::LayoutTaskFactory;
+use layout_traits;
+use layout_traits::{LayoutControlMsg, LayoutTaskFactory};
use script::dom::bindings::js::JS;
-use script::dom::event::ReflowEvent;
use script::dom::node::{ElementNodeTypeId, LayoutDataRef, Node};
use script::dom::element::{HTMLBodyElementTypeId, HTMLHtmlElementTypeId};
-use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery};
+use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery, ScriptLayoutChan};
use script::layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitNowMsg, LayoutQuery};
use script::layout_interface::{HitTestQuery, ContentBoxResponse, HitTestResponse, MouseOverQuery, MouseOverResponse};
use script::layout_interface::{ContentChangedDocumentDamage, LayoutChan, Msg, PrepareToExitMsg};
use script::layout_interface::{QueryMsg, ReapLayoutDataMsg, Reflow, UntrustedNodeAddress};
use script::layout_interface::{ReflowForDisplay, ReflowMsg};
-use script::script_task::{ReflowCompleteMsg, ScriptChan, SendEventMsg};
+use script_traits::{SendEventMsg, ReflowEvent, ReflowCompleteMsg, OpaqueScriptLayoutChannel, ScriptControlChan};
use servo_msg::compositor_msg::Scrollable;
use servo_msg::constellation_msg::{ConstellationChan, PipelineId, Failure, FailureMsg};
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
@@ -55,7 +55,7 @@ use servo_util::time::{TimeProfilerChan, profile};
use servo_util::time;
use servo_util::task::spawn_named_with_send_on_failure;
use servo_util::workqueue::WorkQueue;
-use std::comm::{channel, Sender, Receiver};
+use std::comm::{channel, Sender, Receiver, Select};
use std::mem;
use std::ptr;
use style::{AuthorOrigin, Stylesheet, Stylist};
@@ -68,9 +68,12 @@ pub struct LayoutTask {
/// The ID of the pipeline that we belong to.
pub id: PipelineId,
- /// The port on which we receive messages.
+ /// The port on which we receive messages from the script task.
pub port: Receiver<Msg>,
+ /// The port on which we receive messages from the constellation
+ pub pipeline_port: Receiver<LayoutControlMsg>,
+
//// The channel to send messages to ourself.
pub chan: LayoutChan,
@@ -78,7 +81,7 @@ pub struct LayoutTask {
pub constellation_chan: ConstellationChan,
/// The channel on which messages can be sent to the script task.
- pub script_chan: ScriptChan,
+ pub script_chan: ScriptControlChan,
/// The channel on which messages can be sent to the painting task.
pub render_chan: RenderChan,
@@ -258,7 +261,7 @@ impl<'a> BuildDisplayListTraversal<'a> {
struct LayoutImageResponder {
id: PipelineId,
- script_chan: ScriptChan,
+ script_chan: ScriptControlChan,
}
impl ImageResponder for LayoutImageResponder {
@@ -266,7 +269,7 @@ impl ImageResponder for LayoutImageResponder {
let id = self.id.clone();
let script_chan = self.script_chan.clone();
let f: proc(ImageResponseMsg):Send = proc(_) {
- let ScriptChan(chan) = script_chan;
+ let ScriptControlChan(chan) = script_chan;
drop(chan.send_opt(SendEventMsg(id.clone(), ReflowEvent)))
};
f
@@ -277,11 +280,11 @@ impl LayoutTaskFactory for LayoutTask {
/// Spawns a new layout task.
fn create(_phantom: Option<&mut LayoutTask>,
id: PipelineId,
- port: Receiver<Msg>,
- chan: LayoutChan,
+ chan: OpaqueScriptLayoutChannel,
+ pipeline_port: Receiver<LayoutControlMsg>,
constellation_chan: ConstellationChan,
failure_msg: Failure,
- script_chan: ScriptChan,
+ script_chan: ScriptControlChan,
render_chan: RenderChan,
img_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
@@ -291,9 +294,11 @@ impl LayoutTaskFactory for LayoutTask {
let ConstellationChan(con_chan) = constellation_chan.clone();
spawn_named_with_send_on_failure("LayoutTask", proc() {
{ // Ensures layout task is destroyed before we send shutdown message
+ let sender = chan.sender();
let mut layout = LayoutTask::new(id,
- port,
- chan,
+ chan.receiver(),
+ LayoutChan(sender),
+ pipeline_port,
constellation_chan,
script_chan,
render_chan,
@@ -313,8 +318,9 @@ impl LayoutTask {
fn new(id: PipelineId,
port: Receiver<Msg>,
chan: LayoutChan,
+ pipeline_port: Receiver<LayoutControlMsg>,
constellation_chan: ConstellationChan,
- script_chan: ScriptChan,
+ script_chan: ScriptControlChan,
render_chan: RenderChan,
image_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
@@ -332,6 +338,7 @@ impl LayoutTask {
LayoutTask {
id: id,
port: port,
+ pipeline_port: pipeline_port,
chan: chan,
constellation_chan: constellation_chan,
script_chan: script_chan,
@@ -373,9 +380,45 @@ impl LayoutTask {
}
}
- /// Receives and dispatches messages from the port.
+ /// Receives and dispatches messages from the script and constellation tasks
fn handle_request(&mut self) -> bool {
- match self.port.recv() {
+ enum PortToRead {
+ Pipeline,
+ Script,
+ }
+
+ let port_to_read = {
+ let sel = Select::new();
+ let mut port1 = sel.handle(&self.port);
+ let mut port2 = sel.handle(&self.pipeline_port);
+ unsafe {
+ port1.add();
+ port2.add();
+ }
+ let ret = sel.wait();
+ if ret == port1.id() {
+ Script
+ } else if ret == port2.id() {
+ Pipeline
+ } else {
+ fail!("invalid select result");
+ }
+ };
+
+ match port_to_read {
+ Pipeline => match self.pipeline_port.recv() {
+ layout_traits::ExitNowMsg => self.handle_script_request(ExitNowMsg),
+ },
+ Script => {
+ let msg = self.port.recv();
+ self.handle_script_request(msg)
+ }
+ }
+ }
+
+ /// Receives and dispatches messages from the script task.
+ fn handle_script_request(&mut self, request: Msg) -> bool {
+ match request {
AddStylesheetMsg(sheet) => self.handle_add_stylesheet(sheet),
ReflowMsg(data) => {
profile(time::LayoutPerformCategory, self.time_profiler_chan.clone(), || {
@@ -764,7 +807,7 @@ impl LayoutTask {
// FIXME(pcwalton): This should probably be *one* channel, but we can't fix this without
// either select or a filtered recv() that only looks for messages of a given type.
data.script_join_chan.send(());
- let ScriptChan(ref chan) = data.script_chan;
+ let ScriptControlChan(ref chan) = data.script_chan;
chan.send(ReflowCompleteMsg(self.id, data.id));
}
diff --git a/src/components/layout_traits/layout_traits.rs b/src/components/layout_traits/layout_traits.rs
index 31d0c91683b..572721dee24 100644
--- a/src/components/layout_traits/layout_traits.rs
+++ b/src/components/layout_traits/layout_traits.rs
@@ -9,7 +9,7 @@
#![license = "MPL"]
extern crate gfx;
-extern crate script;
+extern crate script_traits;
extern crate servo_msg = "msg";
extern crate servo_net = "net";
extern crate servo_util = "util";
@@ -26,9 +26,16 @@ use servo_msg::constellation_msg::Failure;
use servo_net::image_cache_task::ImageCacheTask;
use servo_util::opts::Opts;
use servo_util::time::TimeProfilerChan;
-use script::layout_interface::{LayoutChan, Msg};
-use script::script_task::ScriptChan;
-use std::comm::{Sender, Receiver};
+use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel};
+use std::comm::Sender;
+
+/// Messages sent to the layout task from the constellation
+pub enum LayoutControlMsg {
+ ExitNowMsg,
+}
+
+/// A channel wrapper for constellation messages
+pub struct LayoutControlChan(pub Sender<LayoutControlMsg>);
// A static method creating a layout task
// Here to remove the compositor -> layout dependency
@@ -36,11 +43,11 @@ pub trait LayoutTaskFactory {
// FIXME: use a proper static method
fn create(_phantom: Option<&mut Self>,
id: PipelineId,
- port: Receiver<Msg>,
- chan: LayoutChan,
+ chan: OpaqueScriptLayoutChannel,
+ pipeline_port: Receiver<LayoutControlMsg>,
constellation_chan: ConstellationChan,
failure_msg: Failure,
- script_chan: ScriptChan,
+ script_chan: ScriptControlChan,
render_chan: RenderChan,
img_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
diff --git a/src/components/main/servo.rs b/src/components/main/servo.rs
index 09225b9ae96..c4ee380fbdc 100644
--- a/src/components/main/servo.rs
+++ b/src/components/main/servo.rs
@@ -126,7 +126,8 @@ pub fn run(opts: opts::Opts) {
ImageCacheTask::new(resource_task.clone())
};
let font_cache_task = FontCacheTask::new(resource_task.clone());
- let constellation_chan = Constellation::<layout::layout_task::LayoutTask>::start(
+ let constellation_chan = Constellation::<layout::layout_task::LayoutTask,
+ script::script_task::ScriptTask>::start(
compositor_chan,
opts,
resource_task,
diff --git a/src/components/script/dom/event.rs b/src/components/script/dom/event.rs
index 115f9a4024b..15709ad5bc1 100644
--- a/src/components/script/dom/event.rs
+++ b/src/components/script/dom/event.rs
@@ -10,23 +10,11 @@ use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::eventtarget::EventTarget;
-use servo_msg::constellation_msg::WindowSizeData;
use servo_util::str::DOMString;
use std::cell::{Cell, RefCell};
-use geom::point::Point2D;
-
use time;
-pub enum Event_ {
- ResizeEvent(WindowSizeData),
- ReflowEvent,
- ClickEvent(uint, Point2D<f32>),
- MouseDownEvent(uint, Point2D<f32>),
- MouseUpEvent(uint, Point2D<f32>),
- MouseMoveEvent(Point2D<f32>)
-}
-
#[deriving(Encodable)]
pub enum EventPhase {
PhaseNone = EventConstants::NONE as int,
diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs
index 070c2373792..b73b37c4c66 100644
--- a/src/components/script/dom/window.rs
+++ b/src/components/script/dom/window.rs
@@ -21,6 +21,7 @@ use dom::screen::Screen;
use layout_interface::{ReflowForDisplay, DocumentDamageLevel};
use page::Page;
use script_task::{ExitWindowMsg, FireTimerMsg, ScriptChan, TriggerLoadMsg, TriggerFragmentMsg};
+use script_traits::ScriptControlChan;
use servo_msg::compositor_msg::ScriptListener;
use servo_net::image_cache_task::ImageCacheTask;
@@ -73,6 +74,7 @@ impl TimerHandle {
pub struct Window {
eventtarget: EventTarget,
pub script_chan: ScriptChan,
+ control_chan: ScriptControlChan,
console: Cell<Option<JS<Console>>>,
location: Cell<Option<JS<Location>>>,
navigator: Cell<Option<JS<Navigator>>>,
@@ -287,7 +289,7 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
// currently rely on the display list, which means we can't destroy it by
// doing a query reflow.
self.page().damage(damage);
- self.page().reflow(ReflowForDisplay, self.script_chan.clone(), *self.compositor);
+ self.page().reflow(ReflowForDisplay, self.control_chan.clone(), *self.compositor);
}
fn wait_until_safe_to_modify_dom(&self) {
@@ -402,12 +404,14 @@ impl Window {
pub fn new(cx: *mut JSContext,
page: Rc<Page>,
script_chan: ScriptChan,
+ control_chan: ScriptControlChan,
compositor: Box<ScriptListener>,
image_cache_task: ImageCacheTask)
-> Temporary<Window> {
let win = box Window {
eventtarget: EventTarget::new_inherited(WindowTypeId),
script_chan: script_chan,
+ control_chan: control_chan,
console: Cell::new(None),
compositor: Untraceable::new(compositor),
page: page,
diff --git a/src/components/script/layout_interface.rs b/src/components/script/layout_interface.rs
index 0e84554c8a7..892c64414c3 100644
--- a/src/components/script/layout_interface.rs
+++ b/src/components/script/layout_interface.rs
@@ -12,11 +12,13 @@ use dom::node::{Node, LayoutDataRef};
use geom::point::Point2D;
use geom::rect::Rect;
use libc::c_void;
-use script_task::{ScriptChan};
+use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel};
use servo_msg::constellation_msg::WindowSizeData;
use servo_util::geometry::Au;
+use std::any::{Any, AnyRefExt};
use std::cmp;
use std::comm::{channel, Receiver, Sender};
+use std::owned::BoxAny;
use style::Stylesheet;
use url::Url;
@@ -135,7 +137,7 @@ pub struct Reflow {
/// The URL of the page.
pub url: Url,
/// The channel through which messages can be sent back to the script task.
- pub script_chan: ScriptChan,
+ pub script_chan: ScriptControlChan,
/// The current window size.
pub window_size: WindowSizeData,
/// The channel that we send a notification to.
@@ -155,6 +157,31 @@ impl LayoutChan {
}
}
+/// A trait to manage opaque references to script<->layout channels without needing
+/// to expose the message type to crates that don't need to know about them.
+pub trait ScriptLayoutChan {
+ fn new(sender: Sender<Msg>, receiver: Receiver<Msg>) -> Self;
+ fn sender(&self) -> Sender<Msg>;
+ fn receiver(self) -> Receiver<Msg>;
+}
+
+impl ScriptLayoutChan for OpaqueScriptLayoutChannel {
+ fn new(sender: Sender<Msg>, receiver: Receiver<Msg>) -> OpaqueScriptLayoutChannel {
+ let inner = (box sender as Box<Any+Send>, box receiver as Box<Any+Send>);
+ OpaqueScriptLayoutChannel(inner)
+ }
+
+ fn sender(&self) -> Sender<Msg> {
+ let &OpaqueScriptLayoutChannel((ref sender, _)) = self;
+ (*sender.as_ref::<Sender<Msg>>().unwrap()).clone()
+ }
+
+ fn receiver(self) -> Receiver<Msg> {
+ let OpaqueScriptLayoutChannel((_, receiver)) = self;
+ *receiver.downcast::<Receiver<Msg>>().unwrap()
+ }
+}
+
#[test]
fn test_add_damage() {
fn assert_add(mut a: DocumentDamageLevel, b: DocumentDamageLevel,
diff --git a/src/components/script/page.rs b/src/components/script/page.rs
index 8543c887da7..227a6e66e3c 100644
--- a/src/components/script/page.rs
+++ b/src/components/script/page.rs
@@ -17,7 +17,7 @@ use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, Layou
use layout_interface::{LayoutChan, QueryMsg};
use layout_interface::{Reflow, ReflowGoal, ReflowMsg};
use layout_interface::UntrustedNodeAddress;
-use script_task::ScriptChan;
+use script_traits::ScriptControlChan;
use geom::point::Point2D;
use js::rust::Cx;
@@ -301,7 +301,7 @@ impl Page {
/// This function fails if there is no root frame.
pub fn reflow(&self,
goal: ReflowGoal,
- script_chan: ScriptChan,
+ script_chan: ScriptControlChan,
compositor: &ScriptListener) {
let root = match *self.frame() {
diff --git a/src/components/script/script.rs b/src/components/script/script.rs
index 134d032f635..51a7caf8527 100644
--- a/src/components/script/script.rs
+++ b/src/components/script/script.rs
@@ -33,6 +33,7 @@ extern crate net;
extern crate rustrt;
extern crate serialize;
extern crate time;
+extern crate script_traits;
#[phase(plugin)]
extern crate servo_macros = "macros";
extern crate servo_net = "net";
diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs
index 8a9e022312e..d431bc368bf 100644
--- a/src/components/script/script_task.rs
+++ b/src/components/script/script_task.rs
@@ -14,7 +14,6 @@ use dom::bindings::utils::{wrap_for_same_compartment, pre_wrap};
use dom::document::{Document, HTMLDocument, DocumentHelpers};
use dom::element::{Element, HTMLButtonElementTypeId, HTMLInputElementTypeId};
use dom::element::{HTMLSelectElementTypeId, HTMLTextAreaElementTypeId, HTMLOptionElementTypeId};
-use dom::event::{Event_, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
use dom::event::Event;
use dom::uievent::UIEvent;
use dom::eventtarget::{EventTarget, EventTargetHelpers};
@@ -26,7 +25,7 @@ use html::hubbub_html_parser::HtmlParserResult;
use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredScript};
use html::hubbub_html_parser;
use layout_interface::AddStylesheetMsg;
-use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage};
+use layout_interface::{ScriptLayoutChan, LayoutChan, MatchSelectorsDocumentDamage};
use layout_interface::{ReflowDocumentDamage, ReflowForDisplay};
use layout_interface::ContentChangedDocumentDamage;
use layout_interface;
@@ -38,17 +37,23 @@ use js::jsapi::{JSContext, JSRuntime};
use js::rust::{Cx, RtUtils};
use js::rust::with_compartment;
use js;
+use script_traits::{CompositorEvent, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent};
+use script_traits::{MouseMoveEvent, MouseUpEvent, ConstellationControlMsg, ScriptTaskFactory};
+use script_traits::{ResizeMsg, AttachLayoutMsg, LoadMsg, SendEventMsg, ResizeInactiveMsg};
+use script_traits::{ExitPipelineMsg, NewLayoutInfo, OpaqueScriptLayoutChannel, ScriptControlChan};
+use script_traits::ReflowCompleteMsg;
use servo_msg::compositor_msg::{FinishedLoading, LayerId, Loading};
use servo_msg::compositor_msg::{ScriptListener};
use servo_msg::constellation_msg::{ConstellationChan, LoadCompleteMsg, LoadUrlMsg, NavigationDirection};
-use servo_msg::constellation_msg::{PipelineId, SubpageId, Failure, FailureMsg, WindowSizeData};
+use servo_msg::constellation_msg::{PipelineId, Failure, FailureMsg, WindowSizeData};
use servo_msg::constellation_msg;
use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::ResourceTask;
use servo_util::geometry::to_frac_px;
use servo_util::task::spawn_named_with_send_on_failure;
+use std::any::{Any, AnyRefExt};
use std::cell::RefCell;
-use std::comm::{channel, Sender, Receiver};
+use std::comm::{channel, Sender, Receiver, Select};
use std::mem::replace;
use std::rc::Rc;
use url::Url;
@@ -59,42 +64,21 @@ local_data_key!(pub StackRoots: *const RootCollection)
/// Messages used to control the script task.
pub enum ScriptMsg {
- /// Loads a new URL on the specified pipeline.
- LoadMsg(PipelineId, Url),
/// Acts on a fragment URL load on the specified pipeline.
TriggerFragmentMsg(PipelineId, Url),
/// Begins a content-initiated load on the specified pipeline.
TriggerLoadMsg(PipelineId, Url),
- /// Gives a channel and ID to a layout task, as well as the ID of that layout's parent
- AttachLayoutMsg(NewLayoutInfo),
/// Instructs the script task to send a navigate message to the constellation.
NavigateMsg(NavigationDirection),
- /// Sends a DOM event.
- SendEventMsg(PipelineId, Event_),
- /// Window resized. Sends a DOM event eventually, but first we combine events.
- ResizeMsg(PipelineId, WindowSizeData),
/// Fires a JavaScript timeout.
FireTimerMsg(PipelineId, TimerId),
- /// Notifies script that reflow is finished.
- ReflowCompleteMsg(PipelineId, uint),
- /// Notifies script that window has been resized but to not take immediate action.
- ResizeInactiveMsg(PipelineId, WindowSizeData),
- /// Notifies the script that a pipeline should be closed.
- ExitPipelineMsg(PipelineId),
/// Notifies the script that a window associated with a particular pipeline should be closed.
ExitWindowMsg(PipelineId),
/// Notifies the script of progress on a fetch
XHRProgressMsg(TrustedXHRAddress, XHRProgress)
}
-pub struct NewLayoutInfo {
- pub old_pipeline_id: PipelineId,
- pub new_pipeline_id: PipelineId,
- pub subpage_id: SubpageId,
- pub layout_chan: LayoutChan,
-}
-
-/// Encapsulates external communication with the script task.
+/// Encapsulates internal communication within the script task.
#[deriving(Clone)]
pub struct ScriptChan(pub Sender<ScriptMsg>);
@@ -141,10 +125,17 @@ pub struct ScriptTask {
/// The port on which the script task receives messages (load URL, exit, etc.)
port: Receiver<ScriptMsg>,
- /// A channel to hand out when some other task needs to be able to respond to a message from
- /// the script task.
+ /// A channel to hand out to script task-based entities that need to be able to enqueue
+ /// events in the event queue.
chan: ScriptChan,
+ /// A channel to hand out to tasks that need to respond to a message from the script task.
+ control_chan: ScriptControlChan,
+
+ /// The port on which the constellation and layout tasks can communicate with the
+ /// script task.
+ control_port: Receiver<ConstellationControlMsg>,
+
/// For communicating load url messages to the constellation
constellation_chan: ConstellationChan,
/// A handle to the compositor for communicating ready state messages.
@@ -212,6 +203,52 @@ impl<'a> PrivateScriptTaskHelpers for JSRef<'a, Node> {
}
}
+impl ScriptTaskFactory for ScriptTask {
+ fn create_layout_channel(_phantom: Option<&mut ScriptTask>) -> OpaqueScriptLayoutChannel {
+ let (chan, port) = channel();
+ ScriptLayoutChan::new(chan, port)
+ }
+
+ fn clone_layout_channel(_phantom: Option<&mut ScriptTask>, pair: &OpaqueScriptLayoutChannel) -> Box<Any+Send> {
+ box pair.sender() as Box<Any+Send>
+ }
+
+ fn create<C:ScriptListener + Send>(
+ _phantom: Option<&mut ScriptTask>,
+ id: PipelineId,
+ compositor: Box<C>,
+ layout_chan: &OpaqueScriptLayoutChannel,
+ control_chan: ScriptControlChan,
+ control_port: Receiver<ConstellationControlMsg>,
+ constellation_chan: ConstellationChan,
+ failure_msg: Failure,
+ resource_task: ResourceTask,
+ image_cache_task: ImageCacheTask,
+ window_size: WindowSizeData) {
+ let ConstellationChan(const_chan) = constellation_chan.clone();
+ let (script_chan, script_port) = channel();
+ let layout_chan = LayoutChan(layout_chan.sender());
+ spawn_named_with_send_on_failure("ScriptTask", proc() {
+ let script_task = ScriptTask::new(id,
+ compositor as Box<ScriptListener>,
+ layout_chan,
+ script_port,
+ ScriptChan(script_chan),
+ control_chan,
+ control_port,
+ constellation_chan,
+ resource_task,
+ image_cache_task,
+ window_size);
+ let mut failsafe = ScriptMemoryFailsafe::new(&*script_task);
+ script_task.start();
+
+ // This must always be the very last operation performed before the task completes
+ failsafe.neuter();
+ }, FailureMsg(failure_msg), const_chan, false);
+ }
+}
+
impl ScriptTask {
/// Creates a new script task.
pub fn new(id: PipelineId,
@@ -219,6 +256,8 @@ impl ScriptTask {
layout_chan: LayoutChan,
port: Receiver<ScriptMsg>,
chan: ScriptChan,
+ control_chan: ScriptControlChan,
+ control_port: Receiver<ConstellationControlMsg>,
constellation_chan: ConstellationChan,
resource_task: ResourceTask,
img_cache_task: ImageCacheTask,
@@ -252,6 +291,8 @@ impl ScriptTask {
port: port,
chan: chan,
+ control_chan: control_chan,
+ control_port: control_port,
constellation_chan: constellation_chan,
compositor: compositor,
@@ -294,36 +335,6 @@ impl ScriptTask {
}
}
- pub fn create<C:ScriptListener + Send>(
- id: PipelineId,
- compositor: Box<C>,
- layout_chan: LayoutChan,
- port: Receiver<ScriptMsg>,
- chan: ScriptChan,
- constellation_chan: ConstellationChan,
- failure_msg: Failure,
- resource_task: ResourceTask,
- image_cache_task: ImageCacheTask,
- window_size: WindowSizeData) {
- let ConstellationChan(const_chan) = constellation_chan.clone();
- spawn_named_with_send_on_failure("ScriptTask", proc() {
- let script_task = ScriptTask::new(id,
- compositor as Box<ScriptListener>,
- layout_chan,
- port,
- chan,
- constellation_chan,
- resource_task,
- image_cache_task,
- window_size);
- let mut failsafe = ScriptMemoryFailsafe::new(&*script_task);
- script_task.start();
-
- // This must always be the very last operation performed before the task completes
- failsafe.neuter();
- }, FailureMsg(failure_msg), const_chan, false);
- }
-
/// Handle incoming control messages.
fn handle_msgs(&self) -> bool {
let roots = RootCollection::new();
@@ -353,15 +364,36 @@ impl ScriptTask {
self.handle_event(id, ResizeEvent(size));
}
+ enum MixedMessage {
+ FromConstellation(ConstellationControlMsg),
+ FromScript(ScriptMsg),
+ }
+
// Store new resizes, and gather all other events.
let mut sequential = vec!();
// Receive at least one message so we don't spinloop.
- let mut event = self.port.recv();
+ let mut event = {
+ let sel = Select::new();
+ let mut port1 = sel.handle(&self.port);
+ let mut port2 = sel.handle(&self.control_port);
+ unsafe {
+ port1.add();
+ port2.add();
+ }
+ let ret = sel.wait();
+ if ret == port1.id() {
+ FromScript(self.port.recv())
+ } else if ret == port2.id() {
+ FromConstellation(self.control_port.recv())
+ } else {
+ fail!("unexpected select result")
+ }
+ };
loop {
match event {
- ResizeMsg(id, size) => {
+ FromConstellation(ResizeMsg(id, size)) => {
let mut page = self.page.borrow_mut();
let page = page.find(id).expect("resize sent to nonexistent pipeline");
page.resize_event.deref().set(Some(size));
@@ -371,9 +403,12 @@ impl ScriptTask {
}
}
- match self.port.try_recv() {
- Err(_) => break,
- Ok(ev) => event = ev,
+ match self.control_port.try_recv() {
+ Err(_) => match self.port.try_recv() {
+ Err(_) => break,
+ Ok(ev) => event = FromScript(ev),
+ },
+ Ok(ev) => event = FromConstellation(ev),
}
}
@@ -381,19 +416,20 @@ impl ScriptTask {
for msg in sequential.move_iter() {
match msg {
// TODO(tkuehn) need to handle auxiliary layouts for iframes
- AttachLayoutMsg(new_layout_info) => self.handle_new_layout(new_layout_info),
- LoadMsg(id, url) => self.load(id, url),
- TriggerLoadMsg(id, url) => self.trigger_load(id, url),
- TriggerFragmentMsg(id, url) => self.trigger_fragment(id, url),
- SendEventMsg(id, event) => self.handle_event(id, event),
- FireTimerMsg(id, timer_id) => self.handle_fire_timer_msg(id, timer_id),
- NavigateMsg(direction) => self.handle_navigate_msg(direction),
- 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) => self.handle_exit_window_msg(id),
- ResizeMsg(..) => fail!("should have handled ResizeMsg already"),
- XHRProgressMsg(addr, progress) => XMLHttpRequest::handle_xhr_progress(addr, progress),
+ FromConstellation(AttachLayoutMsg(new_layout_info)) =>
+ self.handle_new_layout(new_layout_info),
+ FromConstellation(LoadMsg(id, url)) => self.load(id, url),
+ FromScript(TriggerLoadMsg(id, url)) => self.trigger_load(id, url),
+ FromScript(TriggerFragmentMsg(id, url)) => self.trigger_fragment(id, url),
+ FromConstellation(SendEventMsg(id, event)) => self.handle_event(id, event),
+ FromScript(FireTimerMsg(id, timer_id)) => self.handle_fire_timer_msg(id, timer_id),
+ FromScript(NavigateMsg(direction)) => self.handle_navigate_msg(direction),
+ FromConstellation(ReflowCompleteMsg(id, reflow_id)) => self.handle_reflow_complete_msg(id, reflow_id),
+ FromConstellation(ResizeInactiveMsg(id, new_size)) => self.handle_resize_inactive_msg(id, new_size),
+ FromConstellation(ExitPipelineMsg(id)) => if self.handle_exit_pipeline_msg(id) { return false },
+ FromScript(ExitWindowMsg(id)) => self.handle_exit_window_msg(id),
+ FromConstellation(ResizeMsg(..)) => fail!("should have handled ResizeMsg already"),
+ FromScript(XHRProgressMsg(addr, progress)) => XMLHttpRequest::handle_xhr_progress(addr, progress),
}
}
@@ -415,7 +451,9 @@ impl ScriptTask {
task's page tree. This is a bug.");
let new_page = {
let window_size = parent_page.window_size.deref().get();
- Page::new(new_pipeline_id, Some(subpage_id), layout_chan, window_size,
+ Page::new(new_pipeline_id, Some(subpage_id),
+ LayoutChan(layout_chan.as_ref::<Sender<layout_interface::Msg>>().unwrap().clone()),
+ window_size,
parent_page.resource_task.deref().clone(),
self.constellation_chan.clone(),
self.js_context.borrow().get_ref().clone())
@@ -524,7 +562,7 @@ impl ScriptTask {
*page.mut_url() = Some((loaded.clone(), false));
if needs_reflow {
page.damage(ContentChangedDocumentDamage);
- page.reflow(ReflowForDisplay, self.chan.clone(), self.compositor);
+ page.reflow(ReflowForDisplay, self.control_chan.clone(), self.compositor);
}
return;
},
@@ -537,6 +575,7 @@ impl ScriptTask {
let window = Window::new(cx.deref().ptr,
page.clone(),
self.chan.clone(),
+ self.control_chan.clone(),
self.compositor.dup(),
self.image_cache_task.clone()).root();
let document = Document::new(&*window, Some(url.clone()), HTMLDocument, None).root();
@@ -643,7 +682,7 @@ impl ScriptTask {
/// This is the main entry point for receiving and dispatching DOM events.
///
/// TODO: Actually perform DOM event dispatch.
- fn handle_event(&self, pipeline_id: PipelineId, event: Event_) {
+ fn handle_event(&self, pipeline_id: PipelineId, event: CompositorEvent) {
match event {
ResizeEvent(new_size) => {
debug!("script got resize event: {:?}", new_size);
@@ -655,7 +694,7 @@ impl ScriptTask {
let frame = page.frame();
if frame.is_some() {
page.damage(ReflowDocumentDamage);
- page.reflow(ReflowForDisplay, self.chan.clone(), self.compositor)
+ page.reflow(ReflowForDisplay, self.control_chan.clone(), self.compositor)
}
let mut fragment_node = page.fragment_node.get();
@@ -691,7 +730,7 @@ impl ScriptTask {
let frame = page.frame();
if frame.is_some() {
page.damage(MatchSelectorsDocumentDamage);
- page.reflow(ReflowForDisplay, self.chan.clone(), self.compositor)
+ page.reflow(ReflowForDisplay, self.control_chan.clone(), self.compositor)
}
}
@@ -789,7 +828,7 @@ impl ScriptTask {
if target_compare {
if mouse_over_targets.is_some() {
page.damage(MatchSelectorsDocumentDamage);
- page.reflow(ReflowForDisplay, self.chan.clone(), self.compositor);
+ page.reflow(ReflowForDisplay, self.control_chan.clone(), self.compositor);
}
*mouse_over_targets = Some(target_list);
}
diff --git a/src/components/script_traits/script_traits.rs b/src/components/script_traits/script_traits.rs
new file mode 100644
index 00000000000..26837b91612
--- /dev/null
+++ b/src/components/script_traits/script_traits.rs
@@ -0,0 +1,98 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#![crate_name = "script_traits"]
+#![crate_type = "rlib"]
+
+#![comment = "The Servo Parallel Browser Project"]
+#![license = "MPL"]
+
+extern crate geom;
+extern crate servo_msg = "msg";
+extern crate servo_net = "net";
+extern crate url = "url_";
+extern crate std;
+extern crate serialize;
+
+// This module contains traits in script used generically
+// in the rest of Servo.
+// The traits are here instead of in layout so
+// that these modules won't have to depend on script.
+
+use servo_msg::constellation_msg::{ConstellationChan, PipelineId, Failure, WindowSizeData};
+use servo_msg::constellation_msg::SubpageId;
+use servo_msg::compositor_msg::ScriptListener;
+use servo_net::image_cache_task::ImageCacheTask;
+use servo_net::resource_task::ResourceTask;
+use std::any::Any;
+use url::Url;
+
+use geom::point::Point2D;
+
+use serialize::{Encodable, Encoder};
+
+pub struct NewLayoutInfo {
+ pub old_pipeline_id: PipelineId,
+ pub new_pipeline_id: PipelineId,
+ pub subpage_id: SubpageId,
+ pub layout_chan: Box<Any+Send>, // opaque reference to a LayoutChannel
+}
+
+/// Messages sent from the constellation to the script task
+pub enum ConstellationControlMsg {
+ /// Loads a new URL on the specified pipeline.
+ LoadMsg(PipelineId, Url),
+ /// Gives a channel and ID to a layout task, as well as the ID of that layout's parent
+ AttachLayoutMsg(NewLayoutInfo),
+ /// Window resized. Sends a DOM event eventually, but first we combine events.
+ ResizeMsg(PipelineId, WindowSizeData),
+ /// Notifies script that window has been resized but to not take immediate action.
+ ResizeInactiveMsg(PipelineId, WindowSizeData),
+ /// Notifies the script that a pipeline should be closed.
+ ExitPipelineMsg(PipelineId),
+ /// Sends a DOM event.
+ SendEventMsg(PipelineId, CompositorEvent),
+ /// Notifies script that reflow is finished.
+ ReflowCompleteMsg(PipelineId, uint),
+}
+
+/// Events from the compositor that the script task needs to know about
+pub enum CompositorEvent {
+ ResizeEvent(WindowSizeData),
+ ReflowEvent,
+ ClickEvent(uint, Point2D<f32>),
+ MouseDownEvent(uint, Point2D<f32>),
+ MouseUpEvent(uint, Point2D<f32>),
+ MouseMoveEvent(Point2D<f32>)
+}
+
+/// An opaque wrapper around script<->layout channels to avoid leaking message types into
+/// crates that don't need to know about them.
+pub struct OpaqueScriptLayoutChannel(pub (Box<Any+Send>, Box<Any+Send>));
+
+/// Encapsulates external communication with the script task.
+#[deriving(Clone)]
+pub struct ScriptControlChan(pub Sender<ConstellationControlMsg>);
+
+impl<S: Encoder<E>, E> Encodable<S, E> for ScriptControlChan {
+ fn encode(&self, _s: &mut S) -> Result<(), E> {
+ Ok(())
+ }
+}
+
+pub trait ScriptTaskFactory {
+ fn create<C: ScriptListener + Send>(_phantom: Option<&mut Self>,
+ id: PipelineId,
+ compositor: Box<C>,
+ layout_chan: &OpaqueScriptLayoutChannel,
+ control_chan: ScriptControlChan,
+ control_port: Receiver<ConstellationControlMsg>,
+ constellation_msg: ConstellationChan,
+ failure_msg: Failure,
+ resource_task: ResourceTask,
+ image_cache_task: ImageCacheTask,
+ window_size: WindowSizeData);
+ fn create_layout_channel(_phantom: Option<&mut Self>) -> OpaqueScriptLayoutChannel;
+ fn clone_layout_channel(_phantom: Option<&mut Self>, pair: &OpaqueScriptLayoutChannel) -> Box<Any+Send>;
+}