mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Make compositor event handling a Layer trait
This simplifies the way that event handling interacts with the compositor.
This commit is contained in:
parent
0c12f630e6
commit
96f6c53b52
3 changed files with 161 additions and 148 deletions
|
@ -8,8 +8,7 @@ use compositor_task::{GetGraphicsMetadata, CreateOrUpdateRootLayer, CreateOrUpda
|
||||||
use compositor_task::{SetLayerOrigin, Paint, ScrollFragmentPoint, LoadComplete};
|
use compositor_task::{SetLayerOrigin, Paint, ScrollFragmentPoint, LoadComplete};
|
||||||
use compositor_task::{ShutdownComplete, ChangeRenderState, RenderMsgDiscarded};
|
use compositor_task::{ShutdownComplete, ChangeRenderState, RenderMsgDiscarded};
|
||||||
use constellation::SendableFrameTree;
|
use constellation::SendableFrameTree;
|
||||||
use events;
|
use events::{LayerEventHandling, ScrollPositionChanged};
|
||||||
use events::ScrollPositionChanged;
|
|
||||||
use pipeline::CompositionPipeline;
|
use pipeline::CompositionPipeline;
|
||||||
use windowing;
|
use windowing;
|
||||||
use windowing::{FinishedWindowEvent, IdleWindowEvent, LoadUrlWindowEvent, MouseWindowClickEvent};
|
use windowing::{FinishedWindowEvent, IdleWindowEvent, LoadUrlWindowEvent, MouseWindowClickEvent};
|
||||||
|
@ -132,6 +131,11 @@ enum ShutdownState {
|
||||||
FinishedShuttingDown,
|
FinishedShuttingDown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct HitTestResult {
|
||||||
|
layer: Rc<Layer<CompositorData>>,
|
||||||
|
point: TypedPoint2D<LayerPixel, f32>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<Window: WindowMethods> IOCompositor<Window> {
|
impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
fn new(window: Rc<Window>,
|
fn new(window: Rc<Window>,
|
||||||
port: Receiver<Msg>,
|
port: Receiver<Msg>,
|
||||||
|
@ -548,8 +552,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
match self.find_layer_with_pipeline_and_layer_id(pipeline_id, layer_id) {
|
match self.find_layer_with_pipeline_and_layer_id(pipeline_id, layer_id) {
|
||||||
Some(ref layer) => {
|
Some(ref layer) => {
|
||||||
if layer.extra_data.borrow().wants_scroll_events == WantsScrollEvents {
|
if layer.extra_data.borrow().wants_scroll_events == WantsScrollEvents {
|
||||||
events::clamp_scroll_offset_and_scroll_layer(layer.clone(),
|
layer.clamp_scroll_offset_and_scroll_layer(TypedPoint2D(0f32, 0f32) - origin);
|
||||||
TypedPoint2D(0f32, 0f32) - origin);
|
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -720,14 +723,16 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
MouseWindowMouseDownEvent(_, p) => p,
|
MouseWindowMouseDownEvent(_, p) => p,
|
||||||
MouseWindowMouseUpEvent(_, p) => p,
|
MouseWindowMouseUpEvent(_, p) => p,
|
||||||
};
|
};
|
||||||
for layer in self.scene.root.iter() {
|
match self.find_topmost_layer_at_point(point / self.scene.scale) {
|
||||||
events::send_mouse_event(layer.clone(), mouse_window_event, point / self.scene.scale);
|
Some(result) => result.layer.send_mouse_event(mouse_window_event, result.point),
|
||||||
|
None => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_mouse_window_move_event_class(&self, cursor: TypedPoint2D<DevicePixel, f32>) {
|
fn on_mouse_window_move_event_class(&self, cursor: TypedPoint2D<DevicePixel, f32>) {
|
||||||
for layer in self.scene.root.iter() {
|
match self.find_topmost_layer_at_point(cursor / self.scene.scale) {
|
||||||
events::send_mouse_move_event(layer.clone(), cursor / self.scene.scale);
|
Some(result) => result.layer.send_mouse_move_event(result.point),
|
||||||
|
None => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,9 +745,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
let mut scroll = false;
|
let mut scroll = false;
|
||||||
match self.scene.root {
|
match self.scene.root {
|
||||||
Some(ref mut layer) => {
|
Some(ref mut layer) => {
|
||||||
scroll = events::handle_scroll_event(layer.clone(),
|
scroll = layer.handle_scroll_event(delta, cursor) == ScrollPositionChanged;
|
||||||
delta,
|
|
||||||
cursor) == ScrollPositionChanged;
|
|
||||||
}
|
}
|
||||||
None => { }
|
None => { }
|
||||||
}
|
}
|
||||||
|
@ -798,9 +801,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
let cursor = TypedPoint2D(-1f32, -1f32); // Make sure this hits the base layer.
|
let cursor = TypedPoint2D(-1f32, -1f32); // Make sure this hits the base layer.
|
||||||
match self.scene.root {
|
match self.scene.root {
|
||||||
Some(ref mut layer) => {
|
Some(ref mut layer) => {
|
||||||
events::handle_scroll_event(layer.clone(),
|
layer.handle_scroll_event(page_delta, cursor);
|
||||||
page_delta,
|
|
||||||
cursor);
|
|
||||||
}
|
}
|
||||||
None => { }
|
None => { }
|
||||||
}
|
}
|
||||||
|
@ -1002,4 +1003,33 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
||||||
fn recomposite_if(&mut self, result: bool) {
|
fn recomposite_if(&mut self, result: bool) {
|
||||||
self.recomposite = result || self.recomposite;
|
self.recomposite = result || self.recomposite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_topmost_layer_at_point_for_layer(&self,
|
||||||
|
layer: Rc<Layer<CompositorData>>,
|
||||||
|
point: TypedPoint2D<LayerPixel, f32>)
|
||||||
|
-> Option<HitTestResult> {
|
||||||
|
let child_point = point - layer.bounds.borrow().origin;
|
||||||
|
for child in layer.children().iter().rev() {
|
||||||
|
let result = self.find_topmost_layer_at_point_for_layer(child.clone(), child_point);
|
||||||
|
if result.is_some() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let point = point - *layer.content_offset.borrow();
|
||||||
|
if !layer.bounds.borrow().contains(&point) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(HitTestResult { layer: layer, point: point });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_topmost_layer_at_point(&self,
|
||||||
|
point: TypedPoint2D<LayerPixel, f32>)
|
||||||
|
-> Option<HitTestResult> {
|
||||||
|
match self.scene.root {
|
||||||
|
Some(ref layer) => self.find_topmost_layer_at_point_for_layer(layer.clone(), point),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use compositor_task::LayerProperties;
|
use compositor_task::LayerProperties;
|
||||||
use events;
|
use events::LayerEventHandling;
|
||||||
use pipeline::CompositionPipeline;
|
use pipeline::CompositionPipeline;
|
||||||
|
|
||||||
use azure::azure_hl;
|
use azure::azure_hl;
|
||||||
|
@ -88,9 +88,7 @@ impl CompositorData {
|
||||||
|
|
||||||
// Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the
|
// Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the
|
||||||
// cursor position to make sure the scroll isn't propagated downwards.
|
// cursor position to make sure the scroll isn't propagated downwards.
|
||||||
events::handle_scroll_event(layer.clone(),
|
layer.handle_scroll_event(TypedPoint2D(0f32, 0f32), TypedPoint2D(-1f32, -1f32));
|
||||||
TypedPoint2D(0f32, 0f32),
|
|
||||||
TypedPoint2D(-1f32, -1f32));
|
|
||||||
CompositorData::update_layer_except_size(layer, layer_properties);
|
CompositorData::update_layer_except_size(layer, layer_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
use compositor_data::{CompositorData, WantsScrollEvents};
|
use compositor_data::{CompositorData, WantsScrollEvents};
|
||||||
use windowing::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent};
|
use windowing::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent};
|
||||||
use windowing::MouseWindowMouseUpEvent;
|
use windowing::MouseWindowMouseUpEvent;
|
||||||
|
use windowing::WindowMethods;
|
||||||
|
|
||||||
use geom::length::Length;
|
use geom::length::Length;
|
||||||
|
use geom::matrix::identity;
|
||||||
use geom::point::{Point2D, TypedPoint2D};
|
use geom::point::{Point2D, TypedPoint2D};
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::TypedSize2D;
|
use geom::size::TypedSize2D;
|
||||||
|
@ -15,10 +17,6 @@ use layers::layers::Layer;
|
||||||
use script_traits::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent, SendEventMsg};
|
use script_traits::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent, SendEventMsg};
|
||||||
use script_traits::{ScriptControlChan};
|
use script_traits::{ScriptControlChan};
|
||||||
use servo_msg::compositor_msg::FixedPosition;
|
use servo_msg::compositor_msg::FixedPosition;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
|
|
||||||
use geom::matrix::identity;
|
|
||||||
|
|
||||||
trait Clampable {
|
trait Clampable {
|
||||||
fn clamp(&self, mn: &Self, mx: &Self) -> Self;
|
fn clamp(&self, mn: &Self, mx: &Self) -> Self;
|
||||||
|
@ -45,157 +43,144 @@ pub enum ScrollEventResult {
|
||||||
ScrollPositionUnchanged,
|
ScrollPositionUnchanged,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the layer's descendants that don't want scroll events and scroll by a relative
|
pub trait LayerEventHandling {
|
||||||
/// specified amount in page coordinates. This also takes in a cursor position to see if the
|
/// Move the layer's descendants that don't want scroll events and scroll by a relative
|
||||||
/// mouse is over child layers first. If a layer successfully scrolled, returns true; otherwise
|
/// specified amount in page coordinates. This also takes in a cursor position to see if the
|
||||||
/// returns false, so a parent layer can scroll instead.
|
/// mouse is over child layers first. If a layer successfully scrolled returns either
|
||||||
pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>,
|
/// ScrollPositionUnchanged or ScrollPositionChanged. If no layer was targeted by the event
|
||||||
|
/// returns ScrollEventUnhandled.
|
||||||
|
fn handle_scroll_event(&self,
|
||||||
delta: TypedPoint2D<LayerPixel, f32>,
|
delta: TypedPoint2D<LayerPixel, f32>,
|
||||||
cursor: TypedPoint2D<LayerPixel, f32>)
|
cursor: TypedPoint2D<LayerPixel, f32>)
|
||||||
-> ScrollEventResult {
|
-> ScrollEventResult;
|
||||||
// If this layer doesn't want scroll events, neither it nor its children can handle scroll
|
|
||||||
// events.
|
|
||||||
if layer.extra_data.borrow().wants_scroll_events != WantsScrollEvents {
|
|
||||||
return ScrollEventUnhandled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow children to scroll.
|
// Takes in a MouseWindowEvent, determines if it should be passed to children, and
|
||||||
let scroll_offset = layer.extra_data.borrow().scroll_offset;
|
// sends the event off to the appropriate pipeline. NB: the cursor position is in
|
||||||
let new_cursor = cursor - scroll_offset;
|
// page coordinates.
|
||||||
for child in layer.children().iter() {
|
fn send_mouse_event(&self,
|
||||||
let child_bounds = child.bounds.borrow();
|
event: MouseWindowEvent,
|
||||||
if child_bounds.contains(&new_cursor) {
|
cursor: TypedPoint2D<LayerPixel, f32>);
|
||||||
let result = handle_scroll_event(child.clone(),
|
|
||||||
delta,
|
|
||||||
new_cursor - child_bounds.origin);
|
|
||||||
if result != ScrollEventUnhandled {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clamp_scroll_offset_and_scroll_layer(layer, scroll_offset + delta)
|
fn send_mouse_move_event(&self,
|
||||||
|
cursor: TypedPoint2D<LayerPixel, f32>);
|
||||||
|
|
||||||
|
fn clamp_scroll_offset_and_scroll_layer(&self,
|
||||||
|
new_offset: TypedPoint2D<LayerPixel, f32>)
|
||||||
|
-> ScrollEventResult;
|
||||||
|
fn scroll_layer_and_all_child_layers(&self,
|
||||||
|
new_offset: TypedPoint2D<LayerPixel, f32>)
|
||||||
|
-> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_content_size_for_layer(layer: Rc<Layer<CompositorData>>)
|
fn calculate_content_size_for_layer(layer: &Layer<CompositorData>)
|
||||||
-> TypedSize2D<LayerPixel, f32> {
|
-> TypedSize2D<LayerPixel, f32> {
|
||||||
layer.children().iter().fold(Rect::zero(),
|
layer.children().iter().fold(Rect::zero(),
|
||||||
|unioned_rect, child_rect| {
|
|unioned_rect, child_rect| {
|
||||||
unioned_rect.union(&*child_rect.bounds.borrow())
|
unioned_rect.union(&*child_rect.bounds.borrow())
|
||||||
}).size
|
}).size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clamp_scroll_offset_and_scroll_layer(layer: Rc<Layer<CompositorData>>,
|
impl LayerEventHandling for Layer<CompositorData> {
|
||||||
|
fn handle_scroll_event(&self,
|
||||||
|
delta: TypedPoint2D<LayerPixel, f32>,
|
||||||
|
cursor: TypedPoint2D<LayerPixel, f32>)
|
||||||
|
-> ScrollEventResult {
|
||||||
|
// If this layer doesn't want scroll events, neither it nor its children can handle scroll
|
||||||
|
// events.
|
||||||
|
if self.extra_data.borrow().wants_scroll_events != WantsScrollEvents {
|
||||||
|
return ScrollEventUnhandled;
|
||||||
|
}
|
||||||
|
|
||||||
|
//// Allow children to scroll.
|
||||||
|
let scroll_offset = self.extra_data.borrow().scroll_offset;
|
||||||
|
let new_cursor = cursor - scroll_offset;
|
||||||
|
for child in self.children().iter() {
|
||||||
|
let child_bounds = child.bounds.borrow();
|
||||||
|
if child_bounds.contains(&new_cursor) {
|
||||||
|
let result = child.handle_scroll_event(delta, new_cursor - child_bounds.origin);
|
||||||
|
if result != ScrollEventUnhandled {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.clamp_scroll_offset_and_scroll_layer(scroll_offset + delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clamp_scroll_offset_and_scroll_layer(&self,
|
||||||
new_offset: TypedPoint2D<LayerPixel, f32>)
|
new_offset: TypedPoint2D<LayerPixel, f32>)
|
||||||
-> ScrollEventResult {
|
-> ScrollEventResult {
|
||||||
let layer_size = layer.bounds.borrow().size;
|
let layer_size = self.bounds.borrow().size;
|
||||||
let content_size = calculate_content_size_for_layer(layer.clone());
|
let content_size = calculate_content_size_for_layer(self);
|
||||||
let min_x = (layer_size.width - content_size.width).get().min(0.0);
|
let min_x = (layer_size.width - content_size.width).get().min(0.0);
|
||||||
let min_y = (layer_size.height - content_size.height).get().min(0.0);
|
let min_y = (layer_size.height - content_size.height).get().min(0.0);
|
||||||
let new_offset : TypedPoint2D<LayerPixel, f32> =
|
let new_offset : TypedPoint2D<LayerPixel, f32> =
|
||||||
Point2D(Length(new_offset.x.get().clamp(&min_x, &0.0)),
|
Point2D(Length(new_offset.x.get().clamp(&min_x, &0.0)),
|
||||||
Length(new_offset.y.get().clamp(&min_y, &0.0)));
|
Length(new_offset.y.get().clamp(&min_y, &0.0)));
|
||||||
|
|
||||||
if layer.extra_data.borrow().scroll_offset == new_offset {
|
if self.extra_data.borrow().scroll_offset == new_offset {
|
||||||
return ScrollPositionUnchanged;
|
return ScrollPositionUnchanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The scroll offset is just a record of the scroll position of this scrolling root,
|
// The scroll offset is just a record of the scroll position of this scrolling root,
|
||||||
// but scroll_layer_and_all_child_layers actually moves the child layers.
|
// but scroll_layer_and_all_child_layers actually moves the child layers.
|
||||||
layer.extra_data.borrow_mut().scroll_offset = new_offset;
|
self.extra_data.borrow_mut().scroll_offset = new_offset;
|
||||||
|
|
||||||
let mut result = false;
|
let mut result = false;
|
||||||
for child in layer.children().iter() {
|
for child in self.children().iter() {
|
||||||
result |= scroll_layer_and_all_child_layers(child.clone(), new_offset);
|
result |= child.scroll_layer_and_all_child_layers(new_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if result {
|
if result {
|
||||||
return ScrollPositionChanged;
|
return ScrollPositionChanged;
|
||||||
} else {
|
} else {
|
||||||
return ScrollPositionUnchanged;
|
return ScrollPositionUnchanged;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scroll_layer_and_all_child_layers(layer: Rc<Layer<CompositorData>>,
|
|
||||||
new_offset: TypedPoint2D<LayerPixel, f32>)
|
|
||||||
-> bool {
|
|
||||||
let mut result = false;
|
|
||||||
|
|
||||||
// Only scroll this layer if it's not fixed-positioned.
|
|
||||||
if layer.extra_data.borrow().scroll_policy != FixedPosition {
|
|
||||||
let new_offset = new_offset.to_untyped();
|
|
||||||
*layer.transform.borrow_mut() = identity().translate(new_offset.x,
|
|
||||||
new_offset.y,
|
|
||||||
0.0);
|
|
||||||
*layer.content_offset.borrow_mut() = Point2D::from_untyped(&new_offset);
|
|
||||||
result = true
|
|
||||||
}
|
|
||||||
|
|
||||||
let offset_for_children = new_offset + layer.extra_data.borrow().scroll_offset;
|
|
||||||
for child in layer.children().iter() {
|
|
||||||
result |= scroll_layer_and_all_child_layers(child.clone(), offset_for_children);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HitTestResult {
|
|
||||||
layer: Rc<Layer<CompositorData>>,
|
|
||||||
point: TypedPoint2D<LayerPixel, f32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_topmost_layer_at_point(layer: Rc<Layer<CompositorData>>,
|
|
||||||
point: TypedPoint2D<LayerPixel, f32>)
|
|
||||||
-> Option<HitTestResult> {
|
|
||||||
let child_point = point - layer.bounds.borrow().origin;
|
|
||||||
for child in layer.children().iter().rev() {
|
|
||||||
let result = find_topmost_layer_at_point(child.clone(), child_point);
|
|
||||||
if result.is_some() {
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let point = point - *layer.content_offset.borrow();
|
fn send_mouse_event(&self,
|
||||||
if !layer.bounds.borrow().contains(&point) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Some(HitTestResult { layer: layer, point: point });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes in a MouseWindowEvent, determines if it should be passed to children, and
|
|
||||||
// sends the event off to the appropriate pipeline. NB: the cursor position is in
|
|
||||||
// page coordinates.
|
|
||||||
pub fn send_mouse_event(layer: Rc<Layer<CompositorData>>,
|
|
||||||
event: MouseWindowEvent,
|
event: MouseWindowEvent,
|
||||||
cursor: TypedPoint2D<LayerPixel, f32>) {
|
cursor: TypedPoint2D<LayerPixel, f32>) {
|
||||||
match find_topmost_layer_at_point(layer.clone(), cursor) {
|
let event_point = cursor.to_untyped();
|
||||||
Some(result) => {
|
let message = match event {
|
||||||
let event_point = result.point.to_untyped();
|
MouseWindowClickEvent(button, _) => ClickEvent(button, event_point),
|
||||||
let message = match event {
|
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, event_point),
|
||||||
MouseWindowClickEvent(button, _) => ClickEvent(button, event_point),
|
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, event_point),
|
||||||
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, event_point),
|
};
|
||||||
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, event_point),
|
let pipeline = &self.extra_data.borrow().pipeline;
|
||||||
};
|
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
||||||
let pipeline = &result.layer.extra_data.borrow().pipeline;
|
let _ = chan.send_opt(SendEventMsg(pipeline.id.clone(), message));
|
||||||
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
|
||||||
let _ = chan.send_opt(SendEventMsg(pipeline.id.clone(), message));
|
|
||||||
},
|
|
||||||
None => {},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
fn send_mouse_move_event(&self,
|
||||||
|
|
||||||
pub fn send_mouse_move_event(layer: Rc<Layer<CompositorData>>,
|
|
||||||
cursor: TypedPoint2D<LayerPixel, f32>) {
|
cursor: TypedPoint2D<LayerPixel, f32>) {
|
||||||
match find_topmost_layer_at_point(layer.clone(), cursor) {
|
let message = MouseMoveEvent(cursor.to_untyped());
|
||||||
Some(result) => {
|
let pipeline = &self.extra_data.borrow().pipeline;
|
||||||
let message = MouseMoveEvent(result.point.to_untyped());
|
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
||||||
let pipeline = &result.layer.extra_data.borrow().pipeline;
|
let _ = chan.send_opt(SendEventMsg(pipeline.id.clone(), message));
|
||||||
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
|
||||||
let _ = chan.send_opt(SendEventMsg(pipeline.id.clone(), message));
|
|
||||||
},
|
|
||||||
None => {},
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
fn scroll_layer_and_all_child_layers(&self,
|
||||||
|
new_offset: TypedPoint2D<LayerPixel, f32>)
|
||||||
|
-> bool {
|
||||||
|
let mut result = false;
|
||||||
|
|
||||||
|
// Only scroll this layer if it's not fixed-positioned.
|
||||||
|
if self.extra_data.borrow().scroll_policy != FixedPosition {
|
||||||
|
let new_offset = new_offset.to_untyped();
|
||||||
|
*self.transform.borrow_mut() = identity().translate(new_offset.x,
|
||||||
|
new_offset.y,
|
||||||
|
0.0);
|
||||||
|
*self.content_offset.borrow_mut() = Point2D::from_untyped(&new_offset);
|
||||||
|
result = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let offset_for_children = new_offset + self.extra_data.borrow().scroll_offset;
|
||||||
|
for child in self.children().iter() {
|
||||||
|
result |= child.scroll_layer_and_all_child_layers(offset_for_children);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue