mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 16:55:40 +00:00
servo: Merge #3054 - Decouple compositing and script crates (from jdm:script_traits)
Source-Repo: https://github.com/servo/servo Source-Revision: 62c9a779a956b8c53cab824b1a3c569dd983fadb
This commit is contained in:
parent
8de51c00fd
commit
08782936cf
@ -256,7 +256,15 @@ DONE_gfx = $(B)src/components/gfx/libgfx.dummy
|
||||
|
||||
DEPS_gfx = $(CRATE_gfx) $(SRC_gfx) $(DONE_SUBMODULES) $(DONE_util) $(DONE_style) $(DONE_net) $(DONE_msg) $(DONE_macros)
|
||||
|
||||
RFLAGS_script = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/style -L $(B)src/components/net -L $(B)src/components/msg -L$(B)src/components/macros -L$(B)src/components/gfx
|
||||
RFLAGS_script_traits = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/msg -L $(B)src/components/net -L $(B)src/components/util
|
||||
|
||||
SRC_script_traits = $(call rwildcard,$(S)src/components/script_traits/,*.rs)
|
||||
CRATE_script_traits = $(S)src/components/script_traits/script_traits.rs
|
||||
DONE_script_traits = $(B)src/components/script_traits/libscript_traits.dummy
|
||||
|
||||
DEPS_script_traits = $(CRATE_script_traits) $(SRC_script_traits) $(DONE_msg) $(DONE_net)
|
||||
|
||||
RFLAGS_script = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/style -L $(B)src/components/net -L $(B)src/components/msg -L$(B)src/components/macros -L$(B)src/components/gfx -L$(B)src/components/script_traits
|
||||
|
||||
BINDINGS_SRC = $(S)src/components/script/dom/bindings/codegen
|
||||
WEBIDLS_SRC = $(S)src/components/script/dom/webidls
|
||||
@ -269,7 +277,7 @@ SRC_script = $(call rwildcard,$(S)src/components/script/,*.rs) $(AUTOGEN_SRC_scr
|
||||
CRATE_script = $(S)src/components/script/script.rs
|
||||
DONE_script = $(B)src/components/script/libscript.dummy
|
||||
|
||||
DEPS_script = $(CRATE_script) $(SRC_script) $(DONE_SUBMODULES) $(DONE_util) $(DONE_style) $(DONE_net) $(DONE_msg) $(DONE_macros) $(DONE_gfx)
|
||||
DEPS_script = $(CRATE_script) $(SRC_script) $(DONE_SUBMODULES) $(DONE_util) $(DONE_style) $(DONE_net) $(DONE_msg) $(DONE_macros) $(DONE_gfx) $(DONE_script_traits)
|
||||
|
||||
RFLAGS_style = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L$(B)src/components/macros
|
||||
MAKO_ZIP = $(S)src/components/style/Mako-0.9.1.zip
|
||||
@ -281,15 +289,15 @@ DONE_style = $(B)src/components/style/libstyle.dummy
|
||||
|
||||
DEPS_style = $(CRATE_style) $(SRC_style) $(DONE_SUBMODULES) $(DONE_util) $(DONE_macros)
|
||||
|
||||
RFLAGS_layout_traits = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script -L $(B)src/components/style -L $(B)src/components/msg
|
||||
RFLAGS_layout_traits = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script_traits -L $(B)src/components/style -L $(B)src/components/msg
|
||||
|
||||
SRC_layout_traits = $(call rwildcard,$(S)src/components/layout_traits/,*.rs)
|
||||
CRATE_layout_traits = $(S)src/components/layout_traits/layout_traits.rs
|
||||
DONE_layout_traits = $(B)src/components/layout_traits/liblayout_traits.dummy
|
||||
|
||||
DEPS_layout_traits = $(CRATE_layout_traits) $(SRC_layout_traits) $(DONE_script) $(DONE_msg) $(DONE_net) $(DONE_gfx) $(DONE_util)
|
||||
DEPS_layout_traits = $(CRATE_layout_traits) $(SRC_layout_traits) $(DONE_script_traits) $(DONE_msg) $(DONE_net) $(DONE_gfx) $(DONE_util)
|
||||
|
||||
RFLAGS_layout = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script -L $(B)src/components/style -L $(B)src/components/msg -L$(B)src/components/macros -L$(B)src/components/layout_traits
|
||||
RFLAGS_layout = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script -L $(B)src/components/style -L $(B)src/components/msg -L$(B)src/components/macros -L$(B)src/components/layout_traits -L $(B)src/components/script_traits
|
||||
|
||||
SRC_layout = $(call rwildcard,$(S)src/components/layout/,*.rs) $(S)src/components/layout/css/user-agent.css
|
||||
CRATE_layout = $(S)src/components/layout/layout.rs
|
||||
@ -297,22 +305,22 @@ DONE_layout = $(B)src/components/layout/liblayout.dummy
|
||||
|
||||
DEPS_layout = $(CRATE_layout) $(SRC_layout) $(DONE_script) $(DONE_style) $(DONE_msg) $(DONE_macros) $(DONE_gfx) $(DONE_util) $(DONE_layout_traits)
|
||||
|
||||
RFLAGS_compositing = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script -L $(B)src/components/layout_traits -L $(B)src/components/style -L $(B)src/components/msg
|
||||
RFLAGS_compositing = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/layout_traits -L $(B)src/components/script_traits -L $(B)src/components/style -L $(B)src/components/msg
|
||||
|
||||
SRC_compositing = $(call rwildcard,$(S)src/components/compositing/,*.rs)
|
||||
CRATE_compositing = $(S)src/components/compositing/compositing.rs
|
||||
DONE_compositing = $(B)src/components/compositing/libcompositing.dummy
|
||||
|
||||
DEPS_compositing = $(CRATE_compositing) $(SRC_compositing) $(DONE_util) $(DONE_msg) $(DONE_gfx) $(DONE_script) $(DONE_layout_traits) $(DONE_style)
|
||||
DEPS_compositing = $(CRATE_compositing) $(SRC_compositing) $(DONE_util) $(DONE_msg) $(DONE_gfx) $(DONE_layout_traits) $(DONE_script_traits) $(DONE_style)
|
||||
|
||||
RFLAGS_servo = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script -L $(B)src/components/layout_traits -L $(B)src/components/layout -L $(B)src/components/compositing -L $(B)src/components/style -L $(B)src/components/msg -L$(B)src/components/macros
|
||||
RFLAGS_servo = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script -L $(B)src/components/layout_traits -L $(B)src/components/script_traits -L $(B)src/components/layout -L $(B)src/components/compositing -L $(B)src/components/style -L $(B)src/components/msg -L$(B)src/components/macros
|
||||
|
||||
SRC_servo = $(call rwildcard,$(S)src/components/main/,*.rs)
|
||||
CRATE_servo = $(S)src/components/main/servo.rs
|
||||
|
||||
DEPS_servo = $(CRATE_servo) $(SRC_servo) $(DONE_SUBMODULES) $(DONE_util) $(DONE_gfx) $(DONE_script) $(DONE_net) $(DONE_msg) $(DONE_style) $(DONE_macros) $(DONE_layout) $(DONE_layout_traits) $(DONE_compositing)
|
||||
DEPS_servo = $(CRATE_servo) $(SRC_servo) $(DONE_SUBMODULES) $(DONE_util) $(DONE_gfx) $(DONE_script) $(DONE_net) $(DONE_msg) $(DONE_style) $(DONE_macros) $(DONE_layout) $(DONE_layout_traits) $(DONE_script_traits) $(DONE_compositing)
|
||||
|
||||
SERVO_LIB_CRATES = macros util net msg gfx script style layout layout_traits compositing
|
||||
SERVO_LIB_CRATES = macros util net msg gfx script script_traits style layout layout_traits compositing
|
||||
|
||||
# rules that depend on having correct meta-target vars (DEPS_CLEAN, DEPS_servo, etc)
|
||||
# and SERVO_LIB_CRATES
|
||||
@ -379,7 +387,7 @@ servo: $(DEPS_servo)
|
||||
@$(call E, compile: $@)
|
||||
$(Q)$(RUSTC) $(strip $(CFG_RUSTC_FLAGS)) $(RFLAGS_servo) $< --crate-type bin,dylib,rlib
|
||||
|
||||
RFLAGS_embedding = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script -L $(B)src/components/layout -L $(B)src/components/layout_traits -L $(B)src/components/compositing -L $(B)src/components/style -L $(B)src/components/msg -L $(B).. -L $(B)src/components/main -L $(B)src/components/macros -A non_camel_case_types -A unused_variable
|
||||
RFLAGS_embedding = $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script -L $(B)src/components/layout -L $(B)src/components/layout_traits -L $(B)src/components/script_traits -L $(B)src/components/compositing -L $(B)src/components/style -L $(B)src/components/msg -L $(B).. -L $(B)src/components/main -L $(B)src/components/macros -A non_camel_case_types -A unused_variable
|
||||
|
||||
ifeq ($(CFG_OSTYPE),apple-darwin)
|
||||
RFLAGS_embedding += -C link-args="-Wl,-U,_tc_new -Wl,-U,_tc_newarray -Wl,-U,_tc_delete -Wl,-U,_tc_deletearray"
|
||||
|
1
servo/configure
vendored
1
servo/configure
vendored
@ -631,6 +631,7 @@ make_dir ${CFG_BUILD_DIR}src/components/gfx
|
||||
make_dir ${CFG_BUILD_DIR}src/components/layout
|
||||
make_dir ${CFG_BUILD_DIR}src/components/layout_traits
|
||||
make_dir ${CFG_BUILD_DIR}src/components/script
|
||||
make_dir ${CFG_BUILD_DIR}src/components/script_traits
|
||||
make_dir ${CFG_BUILD_DIR}src/components/style
|
||||
make_dir ${CFG_BUILD_DIR}src/components/main
|
||||
make_dir src/test/html/ref
|
||||
|
@ -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)]
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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";
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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() {
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
}
|
||||
|
98
servo/src/components/script_traits/script_traits.rs
Normal file
98
servo/src/components/script_traits/script_traits.rs
Normal file
@ -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>;
|
||||
}
|
Loading…
Reference in New Issue
Block a user