aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Robinson <martin.james.robinson@gmail.com>2014-09-25 08:41:51 -0700
committerMartin Robinson <martin.james.robinson@gmail.com>2014-09-25 08:41:51 -0700
commit0951936abbe4ee4c71b76c14fe073d09236f89fc (patch)
tree03e4d4e08cc886c143954f1e9e8d9faac3abd403
parente9a7b44f688dacd46ce4971a2a79e42d6a80a8fe (diff)
parent65c6689bccdbde22030764adb2b563fcb0f847ca (diff)
downloadservo-0951936abbe4ee4c71b76c14fe073d09236f89fc.tar.gz
servo-0951936abbe4ee4c71b76c14fe073d09236f89fc.zip
Merge pull request #3464 from mrobinson/scroll_offset
Allow iframes to scroll their contents
-rw-r--r--Cargo.lock10
-rw-r--r--components/compositing/compositor.rs42
-rw-r--r--components/compositing/compositor_data.rs15
-rw-r--r--components/compositing/events.rs77
-rw-r--r--ports/cef/Cargo.lock12
5 files changed, 104 insertions, 52 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3c9746c4432..e04ebaa0b67 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -33,7 +33,7 @@ dependencies = [
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype#0b03da276e4bdeae2300596dabc4ccb16733ad70)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#50a294fd997f0c6eb43e9a58ad6e227fdc2a4692)",
"glfw 0.0.1 (git+https://github.com/servo/glfw-rs?ref=servo#7ccfaca315a43d97914e1601c90ad348ef190edf)",
- "layers 0.1.0 (git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7)",
+ "layers 0.1.0 (git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8)",
"opengles 0.1.0 (git+https://github.com/servo/rust-opengles#6776e9c07feb149d34b087039ecf6b2c143e3afc)",
"skia-sys 0.0.20130412 (git+https://github.com/servo/skia#6d696712962fd0d41120b7a414a48417da8e6a92)",
"xlib 0.1.0 (git+https://github.com/servo/rust-xlib#581d4faddec5188d3c3ae5307dbea28aab90644c)",
@@ -66,7 +66,7 @@ dependencies = [
"gfx 0.0.1",
"glfw 0.0.1 (git+https://github.com/servo/glfw-rs?ref=servo#7ccfaca315a43d97914e1601c90ad348ef190edf)",
"glut 0.0.1 (git+https://github.com/servo/rust-glut#01af0162ea0322ad1a40d6adb023a39813605949)",
- "layers 0.1.0 (git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7)",
+ "layers 0.1.0 (git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8)",
"layout_traits 0.0.1",
"msg 0.0.1",
"net 0.0.1",
@@ -181,7 +181,7 @@ dependencies = [
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype#0b03da276e4bdeae2300596dabc4ccb16733ad70)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#50a294fd997f0c6eb43e9a58ad6e227fdc2a4692)",
"harfbuzz 0.1.0 (git+https://github.com/servo/rust-harfbuzz#ad520942cc17232e1a40cdd8a99c2905623d35f6)",
- "layers 0.1.0 (git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7)",
+ "layers 0.1.0 (git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8)",
"msg 0.0.1",
"net 0.0.1",
"plugins 0.0.1",
@@ -265,7 +265,7 @@ dependencies = [
[[package]]
name = "layers"
version = "0.1.0"
-source = "git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7"
+source = "git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8"
dependencies = [
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"egl 0.1.0 (git+https://github.com/servo/rust-egl#88f2a13812ddbce2bf2317221663a61c31b3e220)",
@@ -321,7 +321,7 @@ dependencies = [
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#50a294fd997f0c6eb43e9a58ad6e227fdc2a4692)",
"io_surface 0.1.0 (git+https://github.com/servo/rust-io-surface#7038341220bd7e86e21118fac2cbc6bd50890e47)",
- "layers 0.1.0 (git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7)",
+ "layers 0.1.0 (git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8)",
"url 0.1.0 (git+https://github.com/servo/rust-url#bfdf809365600a7941a77524f9bb065886de3379)",
"util 0.0.1",
]
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index cec9c2b7419..730db1519a3 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -9,6 +9,7 @@ use compositor_task::{SetLayerOrigin, Paint, ScrollFragmentPoint, LoadComplete};
use compositor_task::{ShutdownComplete, ChangeRenderState, RenderMsgDiscarded};
use constellation::SendableFrameTree;
use events;
+use events::ScrollPositionChanged;
use pipeline::CompositionPipeline;
use platform::{Application, Window};
use windowing;
@@ -24,7 +25,7 @@ use azure::azure_hl;
use std::cmp;
use std::time::duration::Duration;
use geom::point::{Point2D, TypedPoint2D};
-use geom::rect::Rect;
+use geom::rect::{Rect, TypedRect};
use geom::size::TypedSize2D;
use geom::scale_factor::ScaleFactor;
use gfx::render_task::{RenderChan, RenderMsg, RenderRequest, UnusedBufferMsg};
@@ -35,8 +36,8 @@ use layers::rendergl::RenderContext;
use layers::scene::Scene;
use opengles::gl2;
use png;
-use servo_msg::compositor_msg::{Blank, Epoch, FixedPosition, FinishedLoading, IdleRenderState};
-use servo_msg::compositor_msg::{LayerId, ReadyState, RenderingRenderState, RenderState};
+use servo_msg::compositor_msg::{Blank, Epoch, FinishedLoading, IdleRenderState, LayerId};
+use servo_msg::compositor_msg::{ReadyState, RenderingRenderState, RenderState, Scrollable};
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, LoadUrlMsg, NavigateMsg};
use servo_msg::constellation_msg::{PipelineId, ResizedWindowMsg, WindowSizeData};
use servo_msg::constellation_msg;
@@ -413,7 +414,8 @@ impl IOCompositor {
Some(ref mut layer) => CompositorData::clear_all_tiles(layer.clone()),
None => { }
}
- self.scene.root = Some(self.create_frame_tree_root_layers(frame_tree));
+ self.scene.root = Some(self.create_frame_tree_root_layers(frame_tree, None));
+ self.scene.set_root_layer_size(self.window_size.as_f32());
// Initialize the new constellation channel by sending it the root window size.
self.constellation_chan = new_constellation_chan;
@@ -421,7 +423,8 @@ impl IOCompositor {
}
fn create_frame_tree_root_layers(&mut self,
- frame_tree: &SendableFrameTree)
+ frame_tree: &SendableFrameTree,
+ frame_rect: Option<TypedRect<PagePx, f32>>)
-> Rc<Layer<CompositorData>> {
// Initialize the ReadyState and RenderState for this pipeline.
self.ready_states.insert(frame_tree.pipeline.id, Blank);
@@ -433,15 +436,22 @@ impl IOCompositor {
id: LayerId::null(),
rect: Rect::zero(),
background_color: azure_hl::Color::new(0., 0., 0., 0.),
- scroll_policy: FixedPosition,
+ scroll_policy: Scrollable,
};
let root_layer = CompositorData::new_layer(frame_tree.pipeline.clone(),
layer_properties,
WantsScrollEvents,
self.opts.tile_size);
+ match frame_rect {
+ Some(ref frame_rect) => {
+ *root_layer.bounds.borrow_mut() = frame_rect * self.device_pixels_per_page_px();
+ }
+ None => {}
+ }
+
for kid in frame_tree.children.iter() {
- root_layer.add_child(self.create_frame_tree_root_layers(&kid.frame_tree));
+ root_layer.add_child(self.create_frame_tree_root_layers(&kid.frame_tree, kid.rect));
}
return root_layer;
}
@@ -490,7 +500,7 @@ impl IOCompositor {
let need_new_root_layer = !self.update_layer_if_exists(layer_properties);
if need_new_root_layer {
let root_layer = self.find_pipeline_root_layer(layer_properties.pipeline_id);
- CompositorData::update_layer(root_layer.clone(), layer_properties);
+ CompositorData::update_layer_except_size(root_layer.clone(), layer_properties);
let root_layer_pipeline = root_layer.extra_data.borrow().pipeline.clone();
let first_child = CompositorData::new_layer(root_layer_pipeline.clone(),
@@ -701,13 +711,15 @@ impl IOCompositor {
self.hidpi_factor = new_hidpi_factor;
self.update_zoom_transform();
}
- if self.window_size != new_size {
- debug!("osmain: window resized to {:?}", new_size);
- self.window_size = new_size;
- self.send_window_size();
- } else {
- debug!("osmain: dropping window resize since size is still {:?}", new_size);
+
+ if self.window_size == new_size {
+ return;
}
+
+ debug!("osmain: window resized to {:?}", new_size);
+ self.window_size = new_size;
+ self.scene.set_root_layer_size(new_size.as_f32());
+ self.send_window_size();
}
fn on_load_url_window_event(&mut self, url_string: String) {
@@ -755,7 +767,7 @@ impl IOCompositor {
delta,
cursor.as_f32(),
window_size,
- scene_scale) || scroll;
+ scene_scale) == ScrollPositionChanged;
}
None => { }
}
diff --git a/components/compositing/compositor_data.rs b/components/compositing/compositor_data.rs
index bbb46603f6a..ad6bcefa8fd 100644
--- a/components/compositing/compositor_data.rs
+++ b/components/compositing/compositor_data.rs
@@ -18,6 +18,7 @@ use layers::platform::surface::NativeSurfaceMethods;
use servo_msg::compositor_msg::{Epoch, LayerId};
use servo_msg::compositor_msg::ScrollPolicy;
use servo_msg::constellation_msg::PipelineId;
+use servo_util::geometry::PagePx;
use std::rc::Rc;
pub struct CompositorData {
@@ -39,6 +40,10 @@ pub struct CompositorData {
/// A monotonically increasing counter that keeps track of the current epoch.
/// add_buffer() calls that don't match the current epoch will be ignored.
pub epoch: Epoch,
+
+ /// The scroll offset originating from this scrolling root. This allows scrolling roots
+ /// to track their current scroll position even while their content_offset does not change.
+ pub scroll_offset: TypedPoint2D<PagePx, f32>,
}
#[deriving(PartialEq, Clone)]
@@ -60,19 +65,24 @@ impl CompositorData {
scroll_policy: layer_properties.scroll_policy,
background_color: layer_properties.background_color,
epoch: layer_properties.epoch,
+ scroll_offset: TypedPoint2D(0., 0.),
};
Rc::new(Layer::new(Rect::from_untyped(&layer_properties.rect),
tile_size, new_compositor_data))
}
- pub fn update_layer(layer: Rc<Layer<CompositorData>>, layer_properties: LayerProperties) {
+ pub fn update_layer_except_size(layer: Rc<Layer<CompositorData>>,
+ layer_properties: LayerProperties) {
layer.extra_data.borrow_mut().epoch = layer_properties.epoch;
+ layer.extra_data.borrow_mut().scroll_policy = layer_properties.scroll_policy;
layer.extra_data.borrow_mut().background_color = layer_properties.background_color;
+ layer.contents_changed();
+ }
+ pub fn update_layer(layer: Rc<Layer<CompositorData>>, layer_properties: LayerProperties) {
let size: TypedSize2D<DevicePixel, f32> = Size2D::from_untyped(&layer_properties.rect.size);
layer.resize(size);
- layer.contents_changed();
// 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. The
@@ -82,6 +92,7 @@ impl CompositorData {
TypedPoint2D(-1f32, -1f32),
size,
ScaleFactor(1.0) /* scene_scale */);
+ CompositorData::update_layer_except_size(layer, layer_properties);
}
pub fn find_layer_with_pipeline_and_layer_id(layer: Rc<Layer<CompositorData>>,
diff --git a/components/compositing/events.rs b/components/compositing/events.rs
index c4e86cae26a..aa1bfc6e2a3 100644
--- a/components/compositing/events.rs
+++ b/components/compositing/events.rs
@@ -8,6 +8,7 @@ use windowing::MouseWindowMouseUpEvent;
use geom::length::Length;
use geom::point::{Point2D, TypedPoint2D};
+use geom::rect::Rect;
use geom::scale_factor::ScaleFactor;
use geom::size::TypedSize2D;
use layers::geometry::DevicePixel;
@@ -39,6 +40,13 @@ impl Clampable for f32 {
}
}
+#[deriving(PartialEq)]
+pub enum ScrollEventResult {
+ ScrollEventUnhandled,
+ ScrollPositionChanged,
+ ScrollPositionUnchanged,
+}
+
/// 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
@@ -48,40 +56,51 @@ pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>,
cursor: TypedPoint2D<DevicePixel, f32>,
window_size: TypedSize2D<DevicePixel, f32>,
scale: ScaleFactor<PagePx, DevicePixel, f32>)
- -> bool {
+ -> 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 false
+ return ScrollEventUnhandled;
}
// Allow children to scroll.
- 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;
+ let scroll_offset = layer.extra_data.borrow().scroll_offset;
+ let scroll_offset_in_device_pixels = scroll_offset * scale;
+ let new_cursor = cursor - scroll_offset_in_device_pixels;
for child in layer.children().iter() {
let child_bounds = child.bounds.borrow();
- if child_bounds.contains(&new_cursor) &&
- handle_scroll_event(child.clone(),
- delta,
- new_cursor - child_bounds.origin,
- child_bounds.size,
- scale) {
- return true
+ if child_bounds.contains(&new_cursor) {
+ let result = handle_scroll_event(child.clone(),
+ delta,
+ new_cursor - child_bounds.origin,
+ child_bounds.size,
+ scale);
+ if result != ScrollEventUnhandled {
+ return result;
+ }
}
}
- clamp_scroll_offset_and_scroll_layer(layer, content_offset + delta, window_size, scale)
+ clamp_scroll_offset_and_scroll_layer(layer,
+ scroll_offset_in_device_pixels + delta,
+ window_size,
+ scale)
+}
+pub fn calculate_content_size_for_layer(layer: Rc<Layer<CompositorData>>)
+ -> TypedSize2D<DevicePixel, f32> {
+ layer.children().iter().fold(Rect::zero(),
+ |unioned_rect, child_rect| {
+ unioned_rect.union(&*child_rect.bounds.borrow())
+ }).size
}
pub fn clamp_scroll_offset_and_scroll_layer(layer: Rc<Layer<CompositorData>>,
new_offset: TypedPoint2D<DevicePixel, f32>,
window_size: TypedSize2D<DevicePixel, f32>,
scale: ScaleFactor<PagePx, DevicePixel, f32>)
- -> bool {
- let layer_size = layer.bounds.borrow().size;
+ -> ScrollEventResult {
+ let layer_size = calculate_content_size_for_layer(layer.clone());
let min_x = (window_size.width - layer_size.width).get().min(0.0);
let min_y = (window_size.height - layer_size.height).get().min(0.0);
let new_offset : TypedPoint2D<DevicePixel, f32> =
@@ -89,15 +108,24 @@ pub fn clamp_scroll_offset_and_scroll_layer(layer: Rc<Layer<CompositorData>>,
Length(new_offset.y.get().clamp(&min_y, &0.0)));
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
+ if layer.extra_data.borrow().scroll_offset == new_offset_in_page_px {
+ return ScrollPositionUnchanged;
}
- // 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() = untyped_new_offset;
- scroll_layer_and_all_child_layers(layer.clone(), new_offset_in_page_px)
+ // 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.
+ layer.extra_data.borrow_mut().scroll_offset = new_offset_in_page_px;
+
+ let mut result = false;
+ for child in layer.children().iter() {
+ result |= scroll_layer_and_all_child_layers(child.clone(), new_offset_in_page_px);
+ }
+
+ if result {
+ return ScrollPositionChanged;
+ } else {
+ return ScrollPositionUnchanged;
+ }
}
fn scroll_layer_and_all_child_layers(layer: Rc<Layer<CompositorData>>,
@@ -115,8 +143,9 @@ fn scroll_layer_and_all_child_layers(layer: Rc<Layer<CompositorData>>,
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(), new_offset);
+ result |= scroll_layer_and_all_child_layers(child.clone(), offset_for_children);
}
return result;
diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock
index c4d77206c38..74fe836c0b3 100644
--- a/ports/cef/Cargo.lock
+++ b/ports/cef/Cargo.lock
@@ -11,7 +11,7 @@ dependencies = [
"glfw 0.0.1 (git+https://github.com/servo/glfw-rs?ref=servo#955dbe919870b0536f79123232d87c0efe3c552e)",
"glut 0.0.1 (git+https://github.com/servo/rust-glut#01af0162ea0322ad1a40d6adb023a39813605949)",
"js 0.1.0 (git+https://github.com/servo/rust-mozjs#41fb0d80a5ed5614ca13a120cdb3281e599d4e04)",
- "layers 0.1.0 (git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7)",
+ "layers 0.1.0 (git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8)",
"plugins 0.0.1",
"msg 0.0.1",
"net 0.0.1",
@@ -45,7 +45,7 @@ dependencies = [
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype#0b03da276e4bdeae2300596dabc4ccb16733ad70)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#50a294fd997f0c6eb43e9a58ad6e227fdc2a4692)",
"glfw 0.0.1 (git+https://github.com/servo/glfw-rs?ref=servo#955dbe919870b0536f79123232d87c0efe3c552e)",
- "layers 0.1.0 (git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7)",
+ "layers 0.1.0 (git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8)",
"opengles 0.1.0 (git+https://github.com/servo/rust-opengles#6776e9c07feb149d34b087039ecf6b2c143e3afc)",
"skia-sys 0.0.20130412 (git+https://github.com/servo/skia#6d696712962fd0d41120b7a414a48417da8e6a92)",
"xlib 0.1.0 (git+https://github.com/servo/rust-xlib#581d4faddec5188d3c3ae5307dbea28aab90644c)",
@@ -78,7 +78,7 @@ dependencies = [
"gfx 0.0.1",
"glfw 0.0.1 (git+https://github.com/servo/glfw-rs?ref=servo#955dbe919870b0536f79123232d87c0efe3c552e)",
"glut 0.0.1 (git+https://github.com/servo/rust-glut#01af0162ea0322ad1a40d6adb023a39813605949)",
- "layers 0.1.0 (git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7)",
+ "layers 0.1.0 (git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8)",
"layout_traits 0.0.1",
"msg 0.0.1",
"net 0.0.1",
@@ -193,7 +193,7 @@ dependencies = [
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype#0b03da276e4bdeae2300596dabc4ccb16733ad70)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#50a294fd997f0c6eb43e9a58ad6e227fdc2a4692)",
"harfbuzz 0.1.0 (git+https://github.com/servo/rust-harfbuzz#ad520942cc17232e1a40cdd8a99c2905623d35f6)",
- "layers 0.1.0 (git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7)",
+ "layers 0.1.0 (git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8)",
"plugins 0.0.1",
"msg 0.0.1",
"net 0.0.1",
@@ -277,7 +277,7 @@ dependencies = [
[[package]]
name = "layers"
version = "0.1.0"
-source = "git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7"
+source = "git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8"
dependencies = [
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"egl 0.1.0 (git+https://github.com/servo/rust-egl#88f2a13812ddbce2bf2317221663a61c31b3e220)",
@@ -337,7 +337,7 @@ dependencies = [
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#50a294fd997f0c6eb43e9a58ad6e227fdc2a4692)",
"io_surface 0.1.0 (git+https://github.com/servo/rust-io-surface#7038341220bd7e86e21118fac2cbc6bd50890e47)",
- "layers 0.1.0 (git+https://github.com/servo/rust-layers#ef89918471815dfced7aaf2f1594d5469f03eab7)",
+ "layers 0.1.0 (git+https://github.com/servo/rust-layers#ed570335738913fb41fc62a024389dfa415962e8)",
"url 0.1.0 (git+https://github.com/servo/rust-url#bfdf809365600a7941a77524f9bb065886de3379)",
"util 0.0.1",
]