Skip to content

Commit

Permalink
Merge pull request #2789 from zwarich/compositor-events
Browse files Browse the repository at this point in the history
Move compositor event handling code to a new `events` module
  • Loading branch information
pcwalton committed Jul 9, 2014
2 parents 5c15c4d + bc0223a commit cb7828c
Show file tree
Hide file tree
Showing 4 changed files with 242 additions and 223 deletions.
1 change: 1 addition & 0 deletions src/components/compositing/compositing.rs
Expand Up @@ -50,6 +50,7 @@ pub use constellation::Constellation;
pub mod compositor_task;

mod compositor_data;
mod events;

mod compositor;
mod headless;
Expand Down
33 changes: 17 additions & 16 deletions src/components/compositing/compositor.rs
Expand Up @@ -8,6 +8,7 @@ use compositor_task::{GetGraphicsMetadata, CreateOrUpdateRootLayer, CreateOrUpda
use compositor_task::{SetLayerClipRect, Paint, ScrollFragmentPoint, LoadComplete};
use compositor_task::{ShutdownComplete, ChangeRenderState};
use constellation::SendableFrameTree;
use events;
use pipeline::CompositionPipeline;
use platform::{Application, Window};
use windowing;
Expand Down Expand Up @@ -444,11 +445,11 @@ impl IOCompositor {
let needs_recomposite = match self.scene.root {
Some(ref mut root_layer) => {
self.fragment_point.take().map_or(false, |fragment_point| {
CompositorData::move(root_layer.clone(),
pipeline_id,
layer_id,
fragment_point,
page_window)
events::move(root_layer.clone(),
pipeline_id,
layer_id,
fragment_point,
page_window)
})
}
None => fail!("Compositor: Tried to scroll to fragment without root layer."),
Expand Down Expand Up @@ -528,7 +529,7 @@ impl IOCompositor {
Some(ref layer) if layer.extra_data.borrow().pipeline.id == pipeline_id &&
!layer.extra_data.borrow().hidden => {
(true,
CompositorData::move(layer.clone(), pipeline_id, layer_id, point, page_window))
events::move(layer.clone(), pipeline_id, layer_id, point, page_window))
}
Some(_) | None => {
self.fragment_point = Some(point);
Expand Down Expand Up @@ -640,14 +641,14 @@ impl IOCompositor {
MouseWindowMouseUpEvent(_, p) => p / scale,
};
for layer in self.scene.root.iter() {
CompositorData::send_mouse_event(layer.clone(), mouse_window_event, point);
events::send_mouse_event(layer.clone(), mouse_window_event, point);
}
}

fn on_mouse_window_move_event_class(&self, cursor: TypedPoint2D<DevicePixel, f32>) {
let scale = self.device_pixels_per_page_px();
for layer in self.scene.root.iter() {
CompositorData::send_mouse_move_event(layer.clone(), cursor / scale);
events::send_mouse_move_event(layer.clone(), cursor / scale);
}
}

Expand All @@ -662,10 +663,10 @@ impl IOCompositor {
let mut scroll = false;
match self.scene.root {
Some(ref mut layer) => {
scroll = CompositorData::handle_scroll_event(layer.clone(),
page_delta,
page_cursor,
page_window) || scroll;
scroll = events::handle_scroll_event(layer.clone(),
page_delta,
page_cursor,
page_window) || scroll;
}
None => { }
}
Expand Down Expand Up @@ -719,10 +720,10 @@ impl IOCompositor {

match self.scene.root {
Some(ref mut layer) => {
CompositorData::handle_scroll_event(layer.clone(),
page_delta,
page_cursor,
page_window);
events::handle_scroll_event(layer.clone(),
page_delta,
page_cursor,
page_window);
}
None => { }
}
Expand Down
213 changes: 6 additions & 207 deletions src/components/compositing/compositor_data.rs
Expand Up @@ -3,23 +3,19 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use compositor_task::LayerProperties;
use events;
use pipeline::CompositionPipeline;
use windowing::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent};
use windowing::{MouseWindowMouseUpEvent};

use azure::azure_hl::Color;
use geom::length::Length;
use geom::matrix::identity;
use geom::point::{Point2D, TypedPoint2D};
use geom::rect::{Rect, TypedRect};
use geom::rect::Rect;
use geom::size::{Size2D, TypedSize2D};
use gfx::render_task::{ReRenderMsg, UnusedBufferMsg};
use layers::layers::{Layer, Flip, LayerBuffer, LayerBufferSet, NoFlip, TextureLayer};
use layers::quadtree::{Tile, Normal, Hidden};
use layers::platform::surface::{NativeCompositingGraphicsContext, NativeSurfaceMethods};
use layers::texturegl::{Texture, TextureTarget};
use script::dom::event::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
use script::script_task::{ScriptChan, SendEventMsg};
use servo_msg::compositor_msg::{Epoch, FixedPosition, LayerId};
use servo_msg::compositor_msg::ScrollPolicy;
use servo_msg::constellation_msg::PipelineId;
Expand Down Expand Up @@ -82,24 +78,6 @@ pub enum WantsScrollEventsFlag {
DoesntWantScrollEvents,
}

trait Clampable {
fn clamp(&self, mn: &Self, mx: &Self) -> Self;
}

impl Clampable for f32 {
/// Returns the number constrained within the range `mn <= self <= mx`.
/// If any of the numbers are `NAN` then `NAN` is returned.
#[inline]
fn clamp(&self, mn: &f32, mx: &f32) -> f32 {
match () {
_ if self.is_nan() => *self,
_ if !(*self <= *mx) => *mx,
_ if !(*self >= *mn) => *mn,
_ => *self,
}
}
}

impl CompositorData {
pub fn new(pipeline: CompositionPipeline,
layer_id: LayerId,
Expand Down Expand Up @@ -169,141 +147,6 @@ impl CompositorData {
Layer::add_child(layer.clone(), new_kid.clone());
}

/// Move the layer's descendants that don't want scroll events and scroll by a relative
/// specified amount in page coordinates. This also takes in a cursor position to see if the
/// mouse is over child layers first. If a layer successfully scrolled, returns true; otherwise
/// returns false, so a parent layer can scroll instead.
pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>,
delta: TypedPoint2D<PagePx, f32>,
cursor: TypedPoint2D<PagePx, f32>,
window_size: TypedSize2D<PagePx, f32>)
-> bool {
// If this layer is hidden, neither it nor its children will scroll.
if layer.extra_data.borrow().hidden {
return false
}

// 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 false
}

// Allow children to scroll.
let cursor = cursor - layer.extra_data.borrow().scroll_offset;
for child in layer.children().iter() {
match child.extra_data.borrow().scissor {
None => {
error!("CompositorData: unable to perform cursor hit test for layer");
}
Some(rect) => {
let rect: TypedRect<PagePx, f32> = Rect::from_untyped(&rect);
if rect.contains(&cursor) &&
CompositorData::handle_scroll_event(child.clone(),
delta,
cursor - rect.origin,
rect.size) {
return true
}
}
}
}

// This scroll event is mine!
// Scroll this layer!
let old_origin = layer.extra_data.borrow().scroll_offset.clone();
layer.extra_data.borrow_mut().scroll_offset = old_origin + delta;

// bounds checking
let page_size = match layer.extra_data.borrow().page_size {
Some(size) => size,
None => fail!("CompositorData: tried to scroll with no page size set"),
};

let window_size = window_size.to_untyped();
let scroll_offset = layer.extra_data.borrow().scroll_offset.to_untyped();

let min_x = (window_size.width - page_size.width).min(0.0);
layer.extra_data.borrow_mut().scroll_offset.x = Length(scroll_offset.x.clamp(&min_x, &0.0));

let min_y = (window_size.height - page_size.height).min(0.0);
layer.extra_data.borrow_mut().scroll_offset.y = Length(scroll_offset.y.clamp(&min_y, &0.0));

if old_origin - layer.extra_data.borrow().scroll_offset == TypedPoint2D(0f32, 0f32) {
return false
}

let offset = layer.extra_data.borrow().scroll_offset.clone();
CompositorData::scroll(layer.clone(), offset)
}

/// Actually scrolls the descendants of a layer that scroll. This is called by
/// `handle_scroll_event` above when it determines that a layer wants to scroll.
fn scroll(layer: Rc<Layer<CompositorData>>,
scroll_offset: TypedPoint2D<PagePx, f32>)
-> bool {
let mut result = false;

// Only scroll this layer if it's not fixed-positioned.
if layer.extra_data.borrow().scroll_policy != FixedPosition {
// Scroll this layer!
layer.extra_data.borrow_mut().scroll_offset = scroll_offset;

let scroll_offset = layer.extra_data.borrow().scroll_offset.clone();
*layer.transform.borrow_mut() = identity().translate(scroll_offset.x.get(), scroll_offset.y.get(), 0.0);

result = true
}

for child in layer.children().iter() {
result = CompositorData::scroll(child.clone(), scroll_offset) || result;
}

result
}

// 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, cursor: TypedPoint2D<PagePx, f32>) {
let cursor = cursor - layer.extra_data.borrow().scroll_offset;
for child in layer.children().iter() {
if child.extra_data.borrow().hidden {
continue;
}

match child.extra_data.borrow().scissor {
None => {
error!("CompositorData: unable to perform cursor hit test for layer");
}
Some(rect) => {
let rect: TypedRect<PagePx, f32> = Rect::from_untyped(&rect);
if rect.contains(&cursor) {
CompositorData::send_mouse_event(child.clone(), event, cursor - rect.origin);
return;
}
}
}
}

// This mouse event is mine!
let message = match event {
MouseWindowClickEvent(button, _) => ClickEvent(button, cursor.to_untyped()),
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 _ = 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 _ = chan.send_opt(SendEventMsg(layer.extra_data.borrow().pipeline.id.clone(), message));
}

// Given the current window size, determine which tiles need to be (re-)rendered and sends them
// off the the appropriate renderer. Returns true if and only if the scene should be repainted.
pub fn send_buffer_requests_recursively(layer: Rc<Layer<CompositorData>>,
Expand Down Expand Up @@ -439,10 +282,10 @@ impl CompositorData {
// 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.
let size: TypedSize2D<PagePx, f32> = Size2D::from_untyped(&scissor.size);
CompositorData::handle_scroll_event(layer.clone(),
TypedPoint2D(0f32, 0f32),
TypedPoint2D(-1f32, -1f32),
size);
events::handle_scroll_event(layer.clone(),
TypedPoint2D(0f32, 0f32),
TypedPoint2D(-1f32, -1f32),
size);
layer.extra_data.borrow_mut().hidden = false;
}
None => {} // Nothing to do
Expand All @@ -451,50 +294,6 @@ impl CompositorData {
CompositorData::set_occlusions(layer.clone());
}

pub fn move(layer: Rc<Layer<CompositorData>>,
pipeline_id: PipelineId,
layer_id: LayerId,
origin: Point2D<f32>,
window_size: TypedSize2D<PagePx, f32>)
-> bool {
// Search children for the right layer to move.
if layer.extra_data.borrow().pipeline.id != pipeline_id ||
layer.extra_data.borrow().id != layer_id {
return layer.children().iter().any(|kid| {
CompositorData::move(kid.clone(), pipeline_id, layer_id, origin, window_size)
});
}

if layer.extra_data.borrow().wants_scroll_events != WantsScrollEvents {
return false
}

// Scroll this layer!
let old_origin = layer.extra_data.borrow().scroll_offset;
layer.extra_data.borrow_mut().scroll_offset = Point2D::from_untyped(&(origin * -1.0));

// bounds checking
let page_size = match layer.extra_data.borrow().page_size {
Some(size) => size,
None => fail!("CompositorData: tried to scroll with no page size set"),
};
let window_size = window_size.to_untyped();
let scroll_offset = layer.extra_data.borrow().scroll_offset.to_untyped();

let min_x = (window_size.width - page_size.width).min(0.0);
layer.extra_data.borrow_mut().scroll_offset.x = Length(scroll_offset.x.clamp(&min_x, &0.0));
let min_y = (window_size.height - page_size.height).min(0.0);
layer.extra_data.borrow_mut().scroll_offset.y = Length(scroll_offset.y.clamp(&min_y, &0.0));

// check to see if we scrolled
if old_origin - layer.extra_data.borrow().scroll_offset == TypedPoint2D(0f32, 0f32) {
return false;
}

let offset = layer.extra_data.borrow().scroll_offset.clone();
CompositorData::scroll(layer.clone(), offset)
}

// Returns whether the layer should be vertically flipped.
#[cfg(target_os="macos")]
fn texture_flip_and_target(cpu_painting: bool, size: Size2D<uint>) -> (Flip, TextureTarget) {
Expand Down

0 comments on commit cb7828c

Please sign in to comment.