diff options
author | Martin Robinson <martin.james.robinson@gmail.com> | 2014-09-25 08:41:51 -0700 |
---|---|---|
committer | Martin Robinson <martin.james.robinson@gmail.com> | 2014-09-25 08:41:51 -0700 |
commit | 0951936abbe4ee4c71b76c14fe073d09236f89fc (patch) | |
tree | 03e4d4e08cc886c143954f1e9e8d9faac3abd403 | |
parent | e9a7b44f688dacd46ce4971a2a79e42d6a80a8fe (diff) | |
parent | 65c6689bccdbde22030764adb2b563fcb0f847ca (diff) | |
download | servo-0951936abbe4ee4c71b76c14fe073d09236f89fc.tar.gz servo-0951936abbe4ee4c71b76c14fe073d09236f89fc.zip |
Merge pull request #3464 from mrobinson/scroll_offset
Allow iframes to scroll their contents
-rw-r--r-- | Cargo.lock | 10 | ||||
-rw-r--r-- | components/compositing/compositor.rs | 42 | ||||
-rw-r--r-- | components/compositing/compositor_data.rs | 15 | ||||
-rw-r--r-- | components/compositing/events.rs | 77 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 12 |
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", ] |