Store content offset in unscaled pixels

Content offset is now stored in unscaled pixels, so that it can be
applied to tile positions during compositor rendering without unscaling
it. This means that when using it in calculations of layer size (stored
in device pixels), we need to scale it. Scene scale is now stored as a
scale rather than a transformation.

Fixes #3269.
Fixes #3042.
This commit is contained in:
Martin Robinson 2014-09-12 11:37:41 -07:00
parent 13ae369dec
commit ea14fca1dc
5 changed files with 89 additions and 100 deletions

View file

@ -7,15 +7,14 @@ use windowing::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEve
use windowing::MouseWindowMouseUpEvent;
use geom::length::Length;
use geom::point::TypedPoint2D;
use geom::point::{Point2D, TypedPoint2D};
use geom::scale_factor::ScaleFactor;
use geom::size::TypedSize2D;
use layers::geometry::DevicePixel;
use layers::layers::Layer;
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_msg::compositor_msg::FixedPosition;
use servo_util::geometry::PagePx;
use std::rc::Rc;
@ -47,7 +46,8 @@ impl Clampable for f32 {
pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>,
delta: TypedPoint2D<DevicePixel, f32>,
cursor: TypedPoint2D<DevicePixel, f32>,
window_size: TypedSize2D<DevicePixel, f32>)
window_size: TypedSize2D<DevicePixel, f32>,
scale: ScaleFactor<PagePx, DevicePixel, f32>)
-> bool {
// If this layer doesn't want scroll events, neither it nor its children can handle scroll
// events.
@ -56,53 +56,60 @@ pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>,
}
// Allow children to scroll.
let content_offset = layer.content_offset.borrow().clone();
let cursor = cursor - content_offset;
let content_offset_in_page_pixels : TypedPoint2D<PagePx, f32> =
Point2D::from_untyped(&*layer.content_offset.borrow());
let content_offset : TypedPoint2D<DevicePixel, f32> = content_offset_in_page_pixels * scale;
let new_cursor = cursor - content_offset;
for child in layer.children().iter() {
let child_bounds = child.bounds.borrow();
if child_bounds.contains(&cursor) &&
if child_bounds.contains(&new_cursor) &&
handle_scroll_event(child.clone(),
delta,
cursor - child_bounds.origin,
child_bounds.size) {
new_cursor - child_bounds.origin,
child_bounds.size,
scale) {
return true
}
}
clamp_scroll_offset_and_scroll_layer(layer, content_offset + delta, window_size)
clamp_scroll_offset_and_scroll_layer(layer, content_offset + delta, window_size, scale)
}
pub fn clamp_scroll_offset_and_scroll_layer(layer: Rc<Layer<CompositorData>>,
mut new_offset: TypedPoint2D<DevicePixel, f32>,
window_size: TypedSize2D<DevicePixel, f32>)
new_offset: TypedPoint2D<DevicePixel, f32>,
window_size: TypedSize2D<DevicePixel, f32>,
scale: ScaleFactor<PagePx, DevicePixel, f32>)
-> bool {
let layer_size = layer.bounds.borrow().size;
let min_x = (window_size.width - layer_size.width).get().min(0.0);
new_offset.x = Length(new_offset.x.get().clamp(&min_x, &0.0));
let min_y = (window_size.height - layer_size.height).get().min(0.0);
new_offset.y = Length(new_offset.y.get().clamp(&min_y, &0.0));
let new_offset : TypedPoint2D<DevicePixel, f32> =
Point2D(Length(new_offset.x.get().clamp(&min_x, &0.0)),
Length(new_offset.y.get().clamp(&min_y, &0.0)));
if *layer.content_offset.borrow() == new_offset {
let new_offset_in_page_px = new_offset / scale;
let untyped_new_offset = new_offset_in_page_px.to_untyped();
if *layer.content_offset.borrow() == untyped_new_offset {
return false
}
// FIXME: This allows the base layer to record the current content offset without
// updating its transform. This should be replaced with something less strange.
*layer.content_offset.borrow_mut() = new_offset;
scroll_layer_and_all_child_layers(layer.clone(), new_offset)
*layer.content_offset.borrow_mut() = untyped_new_offset;
scroll_layer_and_all_child_layers(layer.clone(), new_offset_in_page_px)
}
fn scroll_layer_and_all_child_layers(layer: Rc<Layer<CompositorData>>,
new_offset: TypedPoint2D<DevicePixel, f32>)
new_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 {
*layer.transform.borrow_mut() = identity().translate(new_offset.x.get(),
new_offset.y.get(),
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() = new_offset;
result = true
@ -122,7 +129,9 @@ pub fn send_mouse_event(layer: Rc<Layer<CompositorData>>,
event: MouseWindowEvent,
cursor: TypedPoint2D<DevicePixel, f32>,
device_pixels_per_page_px: ScaleFactor<PagePx, DevicePixel, f32>) {
let cursor = cursor - *layer.content_offset.borrow();
let content_offset = *layer.content_offset.borrow() * device_pixels_per_page_px.get();
let content_offset : TypedPoint2D<DevicePixel, f32> = Point2D::from_untyped(&content_offset);
let cursor = cursor - content_offset;
for child in layer.children().iter() {
let child_bounds = child.bounds.borrow();
if child_bounds.contains(&cursor) {
@ -152,27 +161,3 @@ pub fn send_mouse_move_event(layer: Rc<Layer<CompositorData>>,
let _ = chan.send_opt(SendEventMsg(layer.extra_data.borrow().pipeline.id.clone(), message));
}
pub fn move(layer: Rc<Layer<CompositorData>>,
pipeline_id: PipelineId,
layer_id: LayerId,
origin: TypedPoint2D<DevicePixel, f32>,
window_size: TypedSize2D<DevicePixel, 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| {
move(kid.clone(),
pipeline_id,
layer_id,
origin,
window_size)
});
}
if layer.extra_data.borrow().wants_scroll_events != WantsScrollEvents {
return false
}
clamp_scroll_offset_and_scroll_layer(layer, TypedPoint2D(0f32, 0f32) - origin, window_size)
}