mirror of
https://github.com/servo/servo.git
synced 2025-06-21 15:49:04 +01:00
Send status messages to the compositor
This commit is contained in:
parent
1fbfd7d45e
commit
7b28462193
8 changed files with 80 additions and 11 deletions
|
@ -9,6 +9,8 @@ use windowing::{ApplicationMethods, WindowMethods, WindowMouseEvent, WindowClick
|
||||||
use windowing::{WindowMouseDownEvent, WindowMouseUpEvent};
|
use windowing::{WindowMouseDownEvent, WindowMouseUpEvent};
|
||||||
|
|
||||||
use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent};
|
use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent};
|
||||||
|
use script::compositor_interface::{ReadyState, CompositorInterface};
|
||||||
|
use script::compositor_interface;
|
||||||
|
|
||||||
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods};
|
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods};
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
|
@ -36,6 +38,13 @@ pub struct CompositorTask {
|
||||||
chan: SharedChan<Msg>,
|
chan: SharedChan<Msg>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CompositorInterface for CompositorTask {
|
||||||
|
fn send_compositor_msg(&self, msg: ReadyState) {
|
||||||
|
let msg = ChangeReadyState(msg);
|
||||||
|
self.chan.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CompositorTask {
|
impl CompositorTask {
|
||||||
/// Starts the compositor. Returns an interface that can be used to communicate with the
|
/// Starts the compositor. Returns an interface that can be used to communicate with the
|
||||||
/// compositor and a port which allows notification when the compositor shuts down.
|
/// compositor and a port which allows notification when the compositor shuts down.
|
||||||
|
@ -63,10 +72,12 @@ impl CompositorTask {
|
||||||
|
|
||||||
/// Messages to the compositor.
|
/// Messages to the compositor.
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
/// Requests that the compositor paint the given layer buffer set for the given page size.
|
|
||||||
Paint(LayerBufferSet, Size2D<uint>),
|
|
||||||
/// Requests that the compositor shut down.
|
/// Requests that the compositor shut down.
|
||||||
Exit,
|
Exit,
|
||||||
|
/// Requests that the compositor paint the given layer buffer set for the given page size.
|
||||||
|
Paint(LayerBufferSet, Size2D<uint>),
|
||||||
|
/// Alerts the compositor to the current status of page loading
|
||||||
|
ChangeReadyState(ReadyState),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Azure surface wrapping to work with the layers infrastructure.
|
/// Azure surface wrapping to work with the layers infrastructure.
|
||||||
|
@ -134,12 +145,19 @@ fn run_main_loop(port: Port<Msg>,
|
||||||
let check_for_messages: @fn() = || {
|
let check_for_messages: @fn() = || {
|
||||||
// Periodically check if the script task responded to our last resize event
|
// Periodically check if the script task responded to our last resize event
|
||||||
resize_rate_limiter.check_resize_response();
|
resize_rate_limiter.check_resize_response();
|
||||||
|
|
||||||
// Handle messages
|
// Handle messages
|
||||||
while port.peek() {
|
while port.peek() {
|
||||||
match port.recv() {
|
match port.recv() {
|
||||||
Exit => *done = true,
|
Exit => *done = true,
|
||||||
|
|
||||||
|
ChangeReadyState(ready_state) => {
|
||||||
|
let window_title = match ready_state {
|
||||||
|
compositor_interface::FinishedLoading => ~"Servo",
|
||||||
|
_ => fmt!("%? — Servo", ready_state),
|
||||||
|
};
|
||||||
|
window.set_title(window_title);
|
||||||
|
}
|
||||||
|
|
||||||
Paint(new_layer_buffer_set, new_size) => {
|
Paint(new_layer_buffer_set, new_size) => {
|
||||||
debug!("osmain: received new frame");
|
debug!("osmain: received new frame");
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use core::comm::{Port, SharedChan};
|
||||||
use gfx::opts::Opts;
|
use gfx::opts::Opts;
|
||||||
use gfx::render_task::RenderTask;
|
use gfx::render_task::RenderTask;
|
||||||
use gfx::render_task;
|
use gfx::render_task;
|
||||||
|
use script::compositor_interface::{CompositorInterface, ReadyState};
|
||||||
use script::engine_interface::{EngineTask, ExitMsg, LoadUrlMsg, Msg};
|
use script::engine_interface::{EngineTask, ExitMsg, LoadUrlMsg, Msg};
|
||||||
use script::layout_interface::LayoutTask;
|
use script::layout_interface::LayoutTask;
|
||||||
use script::layout_interface;
|
use script::layout_interface;
|
||||||
|
@ -48,13 +49,15 @@ impl Engine {
|
||||||
profiler_chan: ProfilerChan)
|
profiler_chan: ProfilerChan)
|
||||||
-> EngineTask {
|
-> EngineTask {
|
||||||
let (script_port, script_chan) = (Cell(script_port), Cell(script_chan));
|
let (script_port, script_chan) = (Cell(script_port), Cell(script_chan));
|
||||||
let (request_port, request_chan) = comm::stream();
|
let (engine_port, engine_chan) = comm::stream();
|
||||||
let (request_port, request_chan) = (Cell(request_port), SharedChan::new(request_chan));
|
let (engine_port, engine_chan) = (Cell(engine_port), SharedChan::new(engine_chan));
|
||||||
let request_chan_clone = request_chan.clone();
|
let engine_chan_clone = engine_chan.clone();
|
||||||
|
let compositor = Cell(compositor);
|
||||||
let profiler_port = Cell(profiler_port);
|
let profiler_port = Cell(profiler_port);
|
||||||
let opts = Cell(copy *opts);
|
let opts = Cell(copy *opts);
|
||||||
|
|
||||||
do task::spawn {
|
do task::spawn {
|
||||||
|
let compositor = compositor.take();
|
||||||
let render_task = RenderTask::new(compositor.clone(),
|
let render_task = RenderTask::new(compositor.clone(),
|
||||||
opts.with_ref(|o| copy *o),
|
opts.with_ref(|o| copy *o),
|
||||||
profiler_chan.clone());
|
profiler_chan.clone());
|
||||||
|
@ -70,16 +73,20 @@ impl Engine {
|
||||||
opts,
|
opts,
|
||||||
profiler_task.chan.clone());
|
profiler_task.chan.clone());
|
||||||
|
|
||||||
|
let compositor_clone = compositor.clone();
|
||||||
let script_task = ScriptTask::new(script_port.take(),
|
let script_task = ScriptTask::new(script_port.take(),
|
||||||
script_chan.take(),
|
script_chan.take(),
|
||||||
request_chan_clone.clone(),
|
engine_chan_clone.clone(),
|
||||||
|
|msg: ReadyState| {
|
||||||
|
compositor_clone.send_compositor_msg(msg)
|
||||||
|
},
|
||||||
layout_task.clone(),
|
layout_task.clone(),
|
||||||
resource_task.clone(),
|
resource_task.clone(),
|
||||||
image_cache_task.clone());
|
image_cache_task.clone());
|
||||||
|
|
||||||
|
|
||||||
Engine {
|
Engine {
|
||||||
request_port: request_port.take(),
|
request_port: engine_port.take(),
|
||||||
compositor: compositor.clone(),
|
compositor: compositor.clone(),
|
||||||
render_task: render_task,
|
render_task: render_task,
|
||||||
resource_task: resource_task.clone(),
|
resource_task: resource_task.clone(),
|
||||||
|
@ -89,7 +96,7 @@ impl Engine {
|
||||||
profiler_task: profiler_task,
|
profiler_task: profiler_task,
|
||||||
}.run();
|
}.run();
|
||||||
}
|
}
|
||||||
request_chan.clone()
|
engine_chan.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self) {
|
fn run(&self) {
|
||||||
|
|
|
@ -162,6 +162,10 @@ impl WindowMethods<Application> for Window {
|
||||||
pub fn set_needs_display(@mut self) {
|
pub fn set_needs_display(@mut self) {
|
||||||
glut::post_redisplay()
|
glut::post_redisplay()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_title(@mut self, title: &str) {
|
||||||
|
glut::set_window_title(self.glut_window, title);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
|
|
|
@ -61,5 +61,7 @@ pub trait WindowMethods<A> {
|
||||||
pub fn check_loop(@mut self);
|
pub fn check_loop(@mut self);
|
||||||
/// Schedules a redisplay at the next turn of the event loop.
|
/// Schedules a redisplay at the next turn of the event loop.
|
||||||
pub fn set_needs_display(@mut self);
|
pub fn set_needs_display(@mut self);
|
||||||
|
/// Sets the title of the window
|
||||||
|
pub fn set_title(@mut self, title: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
src/components/script/compositor_interface.rs
Normal file
19
src/components/script/compositor_interface.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
//! The high-level interface from script to compositor. Using this abstract interface helps reduce
|
||||||
|
/// coupling between these two components
|
||||||
|
|
||||||
|
pub enum ReadyState {
|
||||||
|
/// Informs the compositor that a page is loading. Used for setting status
|
||||||
|
Loading,
|
||||||
|
/// Informs the compositor that a page is rendering. Used for setting status
|
||||||
|
Rendering,
|
||||||
|
/// Informs the compositor that a page is finished loading. Used for setting status
|
||||||
|
FinishedLoading,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CompositorInterface: Clone {
|
||||||
|
fn send_compositor_msg(&self, ReadyState);
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use dom::bindings::utils::WrapperCache;
|
use dom::bindings::utils::WrapperCache;
|
||||||
use dom::bindings::window;
|
use dom::bindings::window;
|
||||||
|
|
||||||
use layout_interface::ReflowForScriptQuery;
|
use layout_interface::ReflowForScriptQuery;
|
||||||
use script_task::{ExitMsg, FireTimerMsg, ScriptMsg, ScriptContext};
|
use script_task::{ExitMsg, FireTimerMsg, ScriptMsg, ScriptContext};
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,8 @@ pub mod html {
|
||||||
pub mod hubbub_html_parser;
|
pub mod hubbub_html_parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod layout_interface;
|
pub mod compositor_interface;
|
||||||
pub mod engine_interface;
|
pub mod engine_interface;
|
||||||
|
pub mod layout_interface;
|
||||||
pub mod script_task;
|
pub mod script_task;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
/// The script task is the task that owns the DOM in memory, runs JavaScript, and spawns parsing
|
/// The script task is the task that owns the DOM in memory, runs JavaScript, and spawns parsing
|
||||||
/// and layout tasks.
|
/// and layout tasks.
|
||||||
|
|
||||||
|
use compositor_interface::{ReadyState, Loading, Rendering, FinishedLoading};
|
||||||
use dom::bindings::utils::GlobalStaticData;
|
use dom::bindings::utils::GlobalStaticData;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::Element;
|
use dom::element::Element;
|
||||||
|
@ -68,12 +69,14 @@ impl ScriptTask {
|
||||||
pub fn new(script_port: Port<ScriptMsg>,
|
pub fn new(script_port: Port<ScriptMsg>,
|
||||||
script_chan: SharedChan<ScriptMsg>,
|
script_chan: SharedChan<ScriptMsg>,
|
||||||
engine_task: EngineTask,
|
engine_task: EngineTask,
|
||||||
|
//FIXME(rust #5192): workaround for lack of working ~Trait
|
||||||
|
compositor_task: ~fn(ReadyState),
|
||||||
layout_task: LayoutTask,
|
layout_task: LayoutTask,
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
image_cache_task: ImageCacheTask)
|
image_cache_task: ImageCacheTask)
|
||||||
-> ScriptTask {
|
-> ScriptTask {
|
||||||
let (script_chan_copy, script_port) = (script_chan.clone(), Cell(script_port));
|
let (script_chan_copy, script_port) = (script_chan.clone(), Cell(script_port));
|
||||||
|
let compositor_task = Cell(compositor_task);
|
||||||
// FIXME: rust#6399
|
// FIXME: rust#6399
|
||||||
let mut the_task = task();
|
let mut the_task = task();
|
||||||
the_task.sched_mode(SingleThreaded);
|
the_task.sched_mode(SingleThreaded);
|
||||||
|
@ -82,6 +85,7 @@ impl ScriptTask {
|
||||||
script_port.take(),
|
script_port.take(),
|
||||||
script_chan_copy.clone(),
|
script_chan_copy.clone(),
|
||||||
engine_task.clone(),
|
engine_task.clone(),
|
||||||
|
compositor_task.take(),
|
||||||
resource_task.clone(),
|
resource_task.clone(),
|
||||||
image_cache_task.clone());
|
image_cache_task.clone());
|
||||||
script_context.start();
|
script_context.start();
|
||||||
|
@ -123,6 +127,8 @@ pub struct ScriptContext {
|
||||||
|
|
||||||
/// For communicating load url messages to the engine
|
/// For communicating load url messages to the engine
|
||||||
engine_task: EngineTask,
|
engine_task: EngineTask,
|
||||||
|
/// For communicating loading messages to the compositor
|
||||||
|
compositor_task: ~fn(ReadyState),
|
||||||
|
|
||||||
/// The JavaScript runtime.
|
/// The JavaScript runtime.
|
||||||
js_runtime: js::rust::rt,
|
js_runtime: js::rust::rt,
|
||||||
|
@ -176,6 +182,7 @@ impl ScriptContext {
|
||||||
script_port: Port<ScriptMsg>,
|
script_port: Port<ScriptMsg>,
|
||||||
script_chan: SharedChan<ScriptMsg>,
|
script_chan: SharedChan<ScriptMsg>,
|
||||||
engine_task: EngineTask,
|
engine_task: EngineTask,
|
||||||
|
compositor_task: ~fn(ReadyState),
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
img_cache_task: ImageCacheTask)
|
img_cache_task: ImageCacheTask)
|
||||||
-> @mut ScriptContext {
|
-> @mut ScriptContext {
|
||||||
|
@ -200,6 +207,7 @@ impl ScriptContext {
|
||||||
script_chan: script_chan,
|
script_chan: script_chan,
|
||||||
|
|
||||||
engine_task: engine_task,
|
engine_task: engine_task,
|
||||||
|
compositor_task: compositor_task,
|
||||||
|
|
||||||
js_runtime: js_runtime,
|
js_runtime: js_runtime,
|
||||||
js_context: js_context,
|
js_context: js_context,
|
||||||
|
@ -308,6 +316,12 @@ impl ScriptContext {
|
||||||
self.layout_task.chan.send(layout_interface::ExitMsg)
|
self.layout_task.chan.send(layout_interface::ExitMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tells the compositor when loading starts and finishes
|
||||||
|
// FIXME ~compositor_interface doesn't work right now, which is why this is necessary
|
||||||
|
fn send_compositor_msg(&self, msg: ReadyState) {
|
||||||
|
(self.compositor_task)(msg);
|
||||||
|
}
|
||||||
|
|
||||||
/// The entry point to document loading. Defines bindings, sets up the window and document
|
/// The entry point to document loading. Defines bindings, sets up the window and document
|
||||||
/// objects, parses HTML and CSS, and kicks off initial layout.
|
/// objects, parses HTML and CSS, and kicks off initial layout.
|
||||||
fn load(&mut self, url: Url) {
|
fn load(&mut self, url: Url) {
|
||||||
|
@ -319,6 +333,7 @@ impl ScriptContext {
|
||||||
self.bindings_initialized = true
|
self.bindings_initialized = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.send_compositor_msg(Loading);
|
||||||
// Parse HTML.
|
// Parse HTML.
|
||||||
//
|
//
|
||||||
// Note: We can parse the next document in parallel with any previous documents.
|
// Note: We can parse the next document in parallel with any previous documents.
|
||||||
|
@ -359,6 +374,7 @@ impl ScriptContext {
|
||||||
url: url
|
url: url
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.send_compositor_msg(Rendering);
|
||||||
// Perform the initial reflow.
|
// Perform the initial reflow.
|
||||||
self.damage = Some(DocumentDamage {
|
self.damage = Some(DocumentDamage {
|
||||||
root: root_node,
|
root: root_node,
|
||||||
|
@ -376,6 +392,7 @@ impl ScriptContext {
|
||||||
~"???",
|
~"???",
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
self.send_compositor_msg(FinishedLoading);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends a ping to layout and waits for the response. The response will arrive when the
|
/// Sends a ping to layout and waits for the response. The response will arrive when the
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue