auto merge of #4578 : mrobinson/servo/fix-compositor-timing-issues, r=larsbergstrom

Clean up compositor data structures and fix timing issues that cause Compositor panics.
This commit is contained in:
bors-servo 2015-01-09 15:39:44 -07:00
commit c1d218cf02
2 changed files with 172 additions and 123 deletions

View file

@ -19,7 +19,7 @@ use geom::rect::{Rect, TypedRect};
use geom::size::TypedSize2D;
use geom::scale_factor::ScaleFactor;
use gfx::paint_task::Msg as PaintMsg;
use gfx::paint_task::{PaintChan, PaintRequest};
use gfx::paint_task::PaintRequest;
use layers::geometry::{DevicePixel, LayerPixel};
use layers::layers::{BufferRequest, Layer, LayerBufferSet};
use layers::rendergl;
@ -64,6 +64,9 @@ pub struct IOCompositor<Window: WindowMethods> {
/// The root pipeline.
root_pipeline: Option<CompositionPipeline>,
/// Tracks details about each active pipeline that the compositor knows about.
pipeline_details: HashMap<PipelineId, PipelineDetails>,
/// The canvas to paint a page.
scene: Scene<CompositorData>,
@ -102,12 +105,6 @@ pub struct IOCompositor<Window: WindowMethods> {
/// The time of the last zoom action has started.
zoom_time: f64,
/// Current display/reflow status of each pipeline.
ready_states: HashMap<PipelineId, ReadyState>,
/// Current paint status of each pipeline.
paint_states: HashMap<PipelineId, PaintState>,
/// Whether the page being rendered has loaded completely.
/// Differs from ReadyState because we can finish loading (ready)
/// many times for a single page.
@ -130,9 +127,6 @@ pub struct IOCompositor<Window: WindowMethods> {
/// Pending scroll events.
pending_scroll_events: Vec<ScrollEvent>,
/// PaintTask channels that we know about, used to return unused buffers.
paint_channels: HashMap<PipelineId, PaintChan>,
}
pub struct ScrollEvent {
@ -159,6 +153,27 @@ struct HitTestResult {
point: TypedPoint2D<LayerPixel, f32>,
}
struct PipelineDetails {
/// The pipeline associated with this PipelineDetails object.
pipeline: Option<CompositionPipeline>,
/// The status of this pipeline's ScriptTask.
ready_state: ReadyState,
/// The status of this pipeline's PaintTask.
paint_state: PaintState,
}
impl PipelineDetails {
fn new() -> PipelineDetails {
PipelineDetails {
pipeline: None,
ready_state: ReadyState::Blank,
paint_state: PaintState::Painting,
}
}
}
impl<Window: WindowMethods> IOCompositor<Window> {
fn new(window: Rc<Window>,
sender: Box<CompositorProxy+Send>,
@ -178,6 +193,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
port: receiver,
context: None,
root_pipeline: None,
pipeline_details: HashMap::new(),
scene: Scene::new(Rect {
origin: Point2D::zero(),
size: window_size.as_f32(),
@ -192,8 +208,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
viewport_zoom: ScaleFactor(1.0),
zoom_action: false,
zoom_time: 0f64,
ready_states: HashMap::new(),
paint_states: HashMap::new(),
got_load_complete_message: false,
got_set_frame_tree_message: false,
constellation_chan: constellation_chan,
@ -202,7 +216,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
fragment_point: None,
outstanding_paint_msgs: 0,
last_composite_time: 0,
paint_channels: HashMap::new(),
}
}
@ -347,7 +360,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
(Msg::PaintTaskExited(pipeline_id), ShutdownState::NotShuttingDown) => {
if self.paint_channels.remove(&pipeline_id).is_none() {
if self.pipeline_details.remove(&pipeline_id).is_none() {
panic!("Saw PaintTaskExited message from an unknown pipeline!");
}
}
@ -362,14 +375,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
fn change_ready_state(&mut self, pipeline_id: PipelineId, ready_state: ReadyState) {
match self.ready_states.entry(pipeline_id) {
Occupied(entry) => {
*entry.into_mut() = ready_state;
}
Vacant(entry) => {
entry.set(ready_state);
}
}
self.get_or_create_pipeline_details(pipeline_id).ready_state = ready_state;
self.window.set_ready_state(self.get_earliest_pipeline_ready_state());
// If we're painting in headless mode, schedule a recomposite.
@ -379,27 +385,43 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
fn get_earliest_pipeline_ready_state(&self) -> ReadyState {
if self.ready_states.len() == 0 {
if self.pipeline_details.len() == 0 {
return ReadyState::Blank;
}
return self.ready_states.values().fold(ReadyState::FinishedLoading,
|a, &b| cmp::min(a, b));
return self.pipeline_details.values().fold(ReadyState::FinishedLoading,
|v, ref details| {
cmp::min(v, details.ready_state)
});
}
fn change_paint_state(&mut self, pipeline_id: PipelineId, paint_state: PaintState) {
match self.paint_states.entry(pipeline_id) {
Occupied(entry) => {
*entry.into_mut() = paint_state;
}
Vacant(entry) => {
entry.set(paint_state);
}
}
self.get_or_create_pipeline_details(pipeline_id).paint_state = paint_state;
self.window.set_paint_state(paint_state);
}
pub fn get_or_create_pipeline_details<'a>(&'a mut self,
pipeline_id: PipelineId)
-> &'a mut PipelineDetails {
if !self.pipeline_details.contains_key(&pipeline_id) {
self.pipeline_details.insert(pipeline_id, PipelineDetails::new());
}
return self.pipeline_details.get_mut(&pipeline_id).unwrap();
}
pub fn get_pipeline<'a>(&'a self, pipeline_id: PipelineId) -> &'a CompositionPipeline {
match self.pipeline_details.get(&pipeline_id) {
Some(ref details) => {
match details.pipeline {
Some(ref pipeline) => pipeline,
None => panic!("Compositor layer has an unitialized pipeline ({}).",
pipeline_id),
}
}
None => panic!("Compositor layer has an unknown pipeline ({}).", pipeline_id),
}
}
fn change_page_title(&mut self, _: PipelineId, title: Option<String>) {
self.window.set_page_title(title);
}
@ -409,10 +431,12 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
fn all_pipelines_in_idle_paint_state(&self) -> bool {
if self.ready_states.len() == 0 {
if self.pipeline_details.len() == 0 {
return false;
}
return self.paint_states.values().all(|&value| value == PaintState::Idle);
return self.pipeline_details.values().all(|ref details| {
details.paint_state == PaintState::Idle
});
}
fn has_paint_msg_tracking(&self) -> bool {
@ -454,7 +478,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
// If we have an old root layer, release all old tiles before replacing it.
match self.scene.root {
Some(ref mut layer) => layer.clear_all_tiles(),
Some(ref layer) => layer.clear_all_tiles(self),
None => { }
}
self.scene.root = Some(self.create_frame_tree_root_layers(frame_tree, None));
@ -481,13 +505,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
scroll_policy: ScrollPolicy::Scrollable,
};
let root_layer = CompositorData::new_layer(pipeline.clone(),
layer_properties,
let root_layer = CompositorData::new_layer(layer_properties,
WantsScrollEventsFlag::WantsScrollEvents,
opts::get().tile_size);
if !self.paint_channels.contains_key(&pipeline.id) {
self.paint_channels.insert(pipeline.id, pipeline.paint_chan.clone());
}
self.get_or_create_pipeline_details(pipeline.id).pipeline = Some(pipeline.clone());
// All root layers mask to bounds.
*root_layer.masks_to_bounds.borrow_mut() = true;
@ -504,10 +526,6 @@ impl<Window: WindowMethods> IOCompositor<Window> {
frame_tree: &SendableFrameTree,
frame_rect: Option<TypedRect<PagePx, f32>>)
-> Rc<Layer<CompositorData>> {
// Initialize the ReadyState and PaintState for this pipeline.
self.ready_states.insert(frame_tree.pipeline.id, ReadyState::Blank);
self.paint_states.insert(frame_tree.pipeline.id, PaintState::Painting);
let root_layer = self.create_root_layer_for_pipeline_and_rect(&frame_tree.pipeline,
frame_rect);
for kid in frame_tree.children.iter() {
@ -517,17 +535,25 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
fn update_frame_tree(&mut self, frame_tree_diff: &FrameTreeDiff) {
let parent_layer = self.find_pipeline_root_layer(frame_tree_diff.parent_pipeline.id);
let pipeline_id = frame_tree_diff.parent_pipeline.id;
let parent_layer = match self.find_pipeline_root_layer(pipeline_id) {
Some(root_layer) => root_layer,
None => {
debug!("Ignoring FrameTreeUpdate message for pipeline ({}) shutting down.",
pipeline_id);
return;
}
};
parent_layer.add_child(
self.create_root_layer_for_pipeline_and_rect(&frame_tree_diff.pipeline,
frame_tree_diff.rect));
}
fn find_pipeline_root_layer(&self, pipeline_id: PipelineId) -> Rc<Layer<CompositorData>> {
match self.find_layer_with_pipeline_and_layer_id(pipeline_id, LayerId::null()) {
Some(ref layer) => layer.clone(),
None => panic!("Tried to create or update layer for unknown pipeline"),
fn find_pipeline_root_layer(&self, pipeline_id: PipelineId) -> Option<Rc<Layer<CompositorData>>> {
if !self.pipeline_details.contains_key(&pipeline_id) {
panic!("Tried to create or update layer for unknown pipeline")
}
self.find_layer_with_pipeline_and_layer_id(pipeline_id, LayerId::null())
}
fn update_layer_if_exists(&mut self, properties: LayerProperties) -> bool {
@ -541,14 +567,21 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
fn create_or_update_base_layer(&mut self, layer_properties: LayerProperties) {
let pipeline_id = layer_properties.pipeline_id;
let root_layer = match self.find_pipeline_root_layer(pipeline_id) {
Some(root_layer) => root_layer,
None => {
debug!("Ignoring CreateOrUpdateBaseLayer message for pipeline ({}) shutting down.",
pipeline_id);
return;
}
};
let need_new_base_layer = !self.update_layer_if_exists(layer_properties);
if need_new_base_layer {
let root_layer = self.find_pipeline_root_layer(layer_properties.pipeline_id);
root_layer.update_layer_except_bounds(layer_properties);
let root_layer_pipeline = root_layer.extra_data.borrow().pipeline.clone();
let base_layer = CompositorData::new_layer(
root_layer_pipeline.clone(),
layer_properties,
WantsScrollEventsFlag::DoesntWantScrollEvents,
opts::get().tile_size);
@ -575,10 +608,12 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
fn create_descendant_layer(&self, layer_properties: LayerProperties) {
let root_layer = self.find_pipeline_root_layer(layer_properties.pipeline_id);
let root_layer_pipeline = root_layer.extra_data.borrow().pipeline.clone();
let new_layer = CompositorData::new_layer(root_layer_pipeline,
layer_properties,
let root_layer = match self.find_pipeline_root_layer(layer_properties.pipeline_id) {
Some(root_layer) => root_layer,
None => return, // This pipeline is in the process of shutting down.
};
let new_layer = CompositorData::new_layer(layer_properties,
WantsScrollEventsFlag::DoesntWantScrollEvents,
root_layer.tile_size);
root_layer.add_child(new_layer);
@ -660,17 +695,16 @@ impl<Window: WindowMethods> IOCompositor<Window> {
new_layer_buffer_set: Box<LayerBufferSet>,
epoch: Epoch) {
match self.find_layer_with_pipeline_and_layer_id(pipeline_id, layer_id) {
Some(layer) => self.assign_painted_buffers_to_layer(layer, new_layer_buffer_set, epoch),
None => {
match self.paint_channels.entry(pipeline_id) {
Occupied(entry) => {
let message = PaintMsg::UnusedBuffer(new_layer_buffer_set.buffers);
let _ = entry.get().send_opt(message);
},
Vacant(_) => panic!("Received a buffer from an unknown pipeline!"),
}
Some(layer) => {
self.assign_painted_buffers_to_layer(layer, new_layer_buffer_set, epoch);
return;
}
None => {}
}
let pipeline = self.get_pipeline(pipeline_id);
let message = PaintMsg::UnusedBuffer(new_layer_buffer_set.buffers);
let _ = pipeline.paint_chan.send_opt(message);
}
fn assign_painted_buffers_to_layer(&mut self,
@ -687,7 +721,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
// FIXME(pcwalton): This is going to cause problems with inconsistent frames since
// we only composite one layer at a time.
assert!(layer.add_buffers(new_layer_buffer_set, epoch));
assert!(layer.add_buffers(self, new_layer_buffer_set, epoch));
self.composite_if_necessary();
}
@ -785,7 +819,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
debug!("osmain: loading URL `{}`", url_string);
self.got_load_complete_message = false;
let root_pipeline_id = match self.scene.root {
Some(ref layer) => layer.extra_data.borrow().pipeline.id.clone(),
Some(ref layer) => layer.get_pipeline_id(),
None => panic!("Compositor: Received WindowEvent::LoadUrl without initialized compositor \
layers"),
};
@ -803,14 +837,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
MouseWindowEvent::MouseUp(_, p) => p,
};
match self.find_topmost_layer_at_point(point / self.scene.scale) {
Some(result) => result.layer.send_mouse_event(mouse_window_event, result.point),
Some(result) => result.layer.send_mouse_event(self, mouse_window_event, result.point),
None => {},
}
}
fn on_mouse_window_move_event_class(&self, cursor: TypedPoint2D<DevicePixel, f32>) {
match self.find_topmost_layer_at_point(cursor / self.scene.scale) {
Some(result) => result.layer.send_mouse_move_event(result.point),
Some(result) => result.layer.send_mouse_move_event(self, result.point),
None => {},
}
}
@ -922,25 +956,21 @@ impl<Window: WindowMethods> IOCompositor<Window> {
fn convert_buffer_requests_to_pipeline_requests_map(&self,
requests: Vec<(Rc<Layer<CompositorData>>,
Vec<BufferRequest>)>) ->
HashMap<PipelineId, (PaintChan,
Vec<PaintRequest>)> {
Vec<BufferRequest>)>)
-> HashMap<PipelineId, Vec<PaintRequest>> {
let scale = self.device_pixels_per_page_px();
let mut results:
HashMap<PipelineId, (PaintChan, Vec<PaintRequest>)> = HashMap::new();
let mut results: HashMap<PipelineId, Vec<PaintRequest>> = HashMap::new();
for (layer, mut layer_requests) in requests.into_iter() {
let &(_, ref mut vec) =
match results.entry(layer.extra_data.borrow().pipeline.id) {
Occupied(mut entry) => {
*entry.get_mut() =
(layer.extra_data.borrow().pipeline.paint_chan.clone(), vec!());
entry.into_mut()
}
Vacant(entry) => {
entry.set((layer.extra_data.borrow().pipeline.paint_chan.clone(), vec!()))
}
};
let vec = match results.entry(layer.get_pipeline_id()) {
Occupied(mut entry) => {
*entry.get_mut() = Vec::new();
entry.into_mut()
}
Vacant(entry) => {
entry.set(Vec::new())
}
};
// All the BufferRequests are in layer/device coordinates, but the paint task
// wants to know the page coordinates. We scale them before sending them.
@ -976,7 +1006,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
if layer.extra_data.borrow().id == LayerId::null() {
let layer_rect = Rect(-layer.extra_data.borrow().scroll_offset.to_untyped(),
layer.bounds.borrow().size.to_untyped());
let pipeline = &layer.extra_data.borrow().pipeline;
let pipeline = self.get_pipeline(layer.get_pipeline_id());
let ScriptControlChan(ref chan) = pipeline.script_chan;
chan.send(ConstellationControlMsg::Viewport(pipeline.id.clone(), layer_rect));
}
@ -1012,9 +1042,9 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.convert_buffer_requests_to_pipeline_requests_map(layers_and_requests);
let mut num_paint_msgs_sent = 0;
for (_pipeline_id, (chan, requests)) in pipeline_requests.into_iter() {
for (pipeline_id, requests) in pipeline_requests.into_iter() {
num_paint_msgs_sent += 1;
let _ = chan.send_opt(PaintMsg::Paint(requests));
let _ = self.get_pipeline(pipeline_id).paint_chan.send_opt(PaintMsg::Paint(requests));
}
self.add_outstanding_paint_msg(num_paint_msgs_sent);
@ -1232,7 +1262,7 @@ fn find_layer_with_pipeline_and_layer_id_for_layer(layer: Rc<Layer<CompositorDat
pipeline_id: PipelineId,
layer_id: LayerId)
-> Option<Rc<Layer<CompositorData>>> {
if layer.extra_data.borrow().pipeline.id == pipeline_id &&
if layer.extra_data.borrow().pipeline_id == pipeline_id &&
layer.extra_data.borrow().id == layer_id {
return Some(layer);
}

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use compositor_task::LayerProperties;
use pipeline::CompositionPipeline;
use compositor::IOCompositor;
use windowing::{MouseWindowEvent, WindowMethods};
use azure::azure_hl;
@ -20,13 +20,15 @@ use layers::platform::surface::NativeSurfaceMethods;
use script_traits::CompositorEvent::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
use script_traits::{ScriptControlChan, ConstellationControlMsg};
use servo_msg::compositor_msg::{Epoch, LayerId, ScrollPolicy};
use servo_msg::constellation_msg::PipelineId;
use std::num::Float;
use std::num::FloatMath;
use std::rc::Rc;
pub struct CompositorData {
/// This layer's pipeline. BufferRequests and mouse events will be sent through this.
pub pipeline: CompositionPipeline,
/// This layer's pipeline id. The compositor can associate this id with an
/// actual CompositionPipeline.
pub pipeline_id: PipelineId,
/// The ID of this layer within the pipeline.
pub id: LayerId,
@ -47,13 +49,12 @@ pub struct CompositorData {
}
impl CompositorData {
pub fn new_layer(pipeline: CompositionPipeline,
layer_properties: LayerProperties,
pub fn new_layer(layer_properties: LayerProperties,
wants_scroll_events: WantsScrollEventsFlag,
tile_size: uint)
-> Rc<Layer<CompositorData>> {
let new_compositor_data = CompositorData {
pipeline: pipeline,
pipeline_id: layer_properties.pipeline_id,
id: layer_properties.id,
wants_scroll_events: wants_scroll_events,
scroll_policy: layer_properties.scroll_policy,
@ -68,20 +69,24 @@ impl CompositorData {
}
}
pub trait CompositorLayer {
pub trait CompositorLayer<Window: WindowMethods> {
fn update_layer_except_bounds(&self, layer_properties: LayerProperties);
fn update_layer(&self, layer_properties: LayerProperties);
fn add_buffers(&self, new_buffers: Box<LayerBufferSet>, epoch: Epoch) -> bool;
fn add_buffers(&self,
compositor: &IOCompositor<Window>,
new_buffers: Box<LayerBufferSet>,
epoch: Epoch)
-> bool;
/// Destroys all layer tiles, sending the buffers back to the painter to be destroyed or
/// reused.
fn clear(&self);
fn clear(&self, compositor: &IOCompositor<Window>);
/// Destroys tiles for this layer and all descendent layers, sending the buffers back to the
/// painter to be destroyed or reused.
fn clear_all_tiles(&self);
fn clear_all_tiles(&self, compositor: &IOCompositor<Window>);
/// Destroys all tiles of all layers, including children, *without* sending them back to the
/// painter. You must call this only when the paint task is destined to be going down;
@ -104,10 +109,12 @@ pub trait CompositorLayer {
// sends the event off to the appropriate pipeline. NB: the cursor position is in
// page coordinates.
fn send_mouse_event(&self,
compositor: &IOCompositor<Window>,
event: MouseWindowEvent,
cursor: TypedPoint2D<LayerPixel, f32>);
fn send_mouse_move_event(&self,
compositor: &IOCompositor<Window>,
cursor: TypedPoint2D<LayerPixel, f32>);
fn clamp_scroll_offset_and_scroll_layer(&self,
@ -120,6 +127,9 @@ pub trait CompositorLayer {
/// Return a flag describing how this layer deals with scroll events.
fn wants_scroll_events(&self) -> WantsScrollEventsFlag;
/// Return the pipeline id associated with this layer.
fn get_pipeline_id(&self) -> PipelineId;
}
#[deriving(Copy, PartialEq, Clone)]
@ -165,7 +175,7 @@ pub enum ScrollEventResult {
ScrollPositionUnchanged,
}
impl CompositorLayer for Layer<CompositorData> {
impl<Window: WindowMethods> CompositorLayer<Window> for Layer<CompositorData> {
fn update_layer_except_bounds(&self, layer_properties: LayerProperties) {
self.extra_data.borrow_mut().epoch = layer_properties.epoch;
self.extra_data.borrow_mut().scroll_policy = layer_properties.scroll_policy;
@ -190,33 +200,35 @@ impl CompositorLayer for Layer<CompositorData> {
//
// If the epoch of the message does not match the layer's epoch, the message is ignored, the
// layer buffer set is consumed, and None is returned.
fn add_buffers(&self, new_buffers: Box<LayerBufferSet>, epoch: Epoch) -> bool {
fn add_buffers(&self,
compositor: &IOCompositor<Window>,
new_buffers: Box<LayerBufferSet>,
epoch: Epoch)
-> bool {
if self.extra_data.borrow().epoch != epoch {
debug!("add_buffers: compositor epoch mismatch: {} != {}, id: {}",
self.extra_data.borrow().epoch,
epoch,
self.extra_data.borrow().pipeline.id);
let msg = PaintMsg::UnusedBuffer(new_buffers.buffers);
let _ = self.extra_data.borrow().pipeline.paint_chan.send_opt(msg);
self.get_pipeline_id());
let pipeline = compositor.get_pipeline(self.get_pipeline_id());
let _ = pipeline.paint_chan.send_opt(PaintMsg::UnusedBuffer(new_buffers.buffers));
return false;
}
{
for buffer in new_buffers.buffers.into_iter().rev() {
self.add_buffer(buffer);
}
for buffer in new_buffers.buffers.into_iter().rev() {
self.add_buffer(buffer);
}
let unused_buffers = self.collect_unused_buffers();
if !unused_buffers.is_empty() { // send back unused buffers
let msg = PaintMsg::UnusedBuffer(unused_buffers);
let _ = self.extra_data.borrow().pipeline.paint_chan.send_opt(msg);
}
let unused_buffers = self.collect_unused_buffers();
if !unused_buffers.is_empty() { // send back unused buffers
let pipeline = compositor.get_pipeline(self.get_pipeline_id());
let _ = pipeline.paint_chan.send_opt(PaintMsg::UnusedBuffer(unused_buffers));
}
return true;
}
fn clear(&self) {
fn clear(&self, compositor: &IOCompositor<Window>) {
let mut buffers = self.collect_buffers();
if !buffers.is_empty() {
@ -227,16 +239,17 @@ impl CompositorLayer for Layer<CompositorData> {
buffer.mark_wont_leak()
}
let _ = self.extra_data.borrow().pipeline.paint_chan.send_opt(PaintMsg::UnusedBuffer(buffers));
let pipeline = compositor.get_pipeline(self.get_pipeline_id());
let _ = pipeline.paint_chan.send_opt(PaintMsg::UnusedBuffer(buffers));
}
}
/// Destroys tiles for this layer and all descendent layers, sending the buffers back to the
/// painter to be destroyed or reused.
fn clear_all_tiles(&self) {
self.clear();
fn clear_all_tiles(&self, compositor: &IOCompositor<Window>) {
self.clear(compositor);
for kid in self.children().iter() {
kid.clear_all_tiles();
kid.clear_all_tiles(compositor);
}
}
@ -314,6 +327,7 @@ impl CompositorLayer for Layer<CompositorData> {
}
fn send_mouse_event(&self,
compositor: &IOCompositor<Window>,
event: MouseWindowEvent,
cursor: TypedPoint2D<LayerPixel, f32>) {
let event_point = cursor.to_untyped();
@ -325,15 +339,17 @@ impl CompositorLayer for Layer<CompositorData> {
MouseWindowEvent::MouseUp(button, _) =>
MouseUpEvent(button, event_point),
};
let pipeline = &self.extra_data.borrow().pipeline;
let pipeline = compositor.get_pipeline(self.get_pipeline_id());
let ScriptControlChan(ref chan) = pipeline.script_chan;
let _ = chan.send_opt(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
}
fn send_mouse_move_event(&self,
compositor: &IOCompositor<Window>,
cursor: TypedPoint2D<LayerPixel, f32>) {
let message = MouseMoveEvent(cursor.to_untyped());
let pipeline = &self.extra_data.borrow().pipeline;
let pipeline = compositor.get_pipeline(self.get_pipeline_id());
let ScriptControlChan(ref chan) = pipeline.script_chan;
let _ = chan.send_opt(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
}
@ -362,4 +378,7 @@ impl CompositorLayer for Layer<CompositorData> {
self.extra_data.borrow().wants_scroll_events
}
fn get_pipeline_id(&self) -> PipelineId {
self.extra_data.borrow().pipeline_id
}
}