From 2724c3c6bb02a685c80dcc2266f0ee3cd3d268a8 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Tue, 23 Sep 2014 12:58:23 -0700 Subject: [PATCH 1/6] Store scrolling root scroll offset explicitly Instead of sneakily setting the content offset and not the transform on scrolling roots, let scrolling roots specify their scroll offset directly and separately. This will also be important when adding proper scrolling support for iframes. --- components/compositing/compositor_data.rs | 6 +++++ components/compositing/events.rs | 29 +++++++++++++---------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/components/compositing/compositor_data.rs b/components/compositing/compositor_data.rs index bbb46603f6a..17ce34aab12 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, } #[deriving(PartialEq, Clone)] @@ -60,6 +65,7 @@ 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), diff --git a/components/compositing/events.rs b/components/compositing/events.rs index c4e86cae26a..0c9136d9936 100644 --- a/components/compositing/events.rs +++ b/components/compositing/events.rs @@ -56,10 +56,9 @@ pub fn handle_scroll_event(layer: Rc>, } // Allow children to scroll. - let content_offset_in_page_pixels : TypedPoint2D = - Point2D::from_untyped(&*layer.content_offset.borrow()); - let content_offset : TypedPoint2D = 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) && @@ -72,8 +71,10 @@ pub fn handle_scroll_event(layer: Rc>, } } - 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 clamp_scroll_offset_and_scroll_layer(layer: Rc>, @@ -89,15 +90,19 @@ pub fn clamp_scroll_offset_and_scroll_layer(layer: Rc>, 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 { + if layer.extra_data.borrow().scroll_offset == new_offset_in_page_px { 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() = 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); + } + return result; } fn scroll_layer_and_all_child_layers(layer: Rc>, From 6bbde703c1b72a5a4ccf7ad2adb8eb8c4ae1ab27 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Mon, 22 Sep 2014 16:32:26 -0700 Subject: [PATCH 2/6] Give root layers a scrollable policy This allows iframe layers to move properly when their parents scroll and is necessary to properly track their masking rects as their children move and to draw their backgrounds in the proper position. --- components/compositing/compositor.rs | 6 +++--- components/compositing/compositor_data.rs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index cec9c2b7419..316efce8c37 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -35,8 +35,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; @@ -433,7 +433,7 @@ 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, diff --git a/components/compositing/compositor_data.rs b/components/compositing/compositor_data.rs index 17ce34aab12..1abb88fbdb3 100644 --- a/components/compositing/compositor_data.rs +++ b/components/compositing/compositor_data.rs @@ -74,6 +74,7 @@ impl CompositorData { pub fn update_layer(layer: Rc>, 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; let size: TypedSize2D = Size2D::from_untyped(&layer_properties.rect.size); From 80433f7ea0bfb3fe0963de87bea5ad60a5c3ea75 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Tue, 23 Sep 2014 16:26:37 -0700 Subject: [PATCH 3/6] Properly size root layers Root layers should be sized to their frame rectangles and the root of the root layers should track the window size. This is important because layers need to be properly sized to scroll. --- Cargo.lock | 10 ++++----- components/compositing/compositor.rs | 31 +++++++++++++++++++--------- ports/cef/Cargo.lock | 12 +++++------ 3 files changed, 32 insertions(+), 21 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 316efce8c37..e752bc37a84 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -24,7 +24,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}; @@ -413,7 +413,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 +422,8 @@ impl IOCompositor { } fn create_frame_tree_root_layers(&mut self, - frame_tree: &SendableFrameTree) + frame_tree: &SendableFrameTree, + frame_rect: Option>) -> Rc> { // Initialize the ReadyState and RenderState for this pipeline. self.ready_states.insert(frame_tree.pipeline.id, Blank); @@ -440,8 +442,15 @@ impl IOCompositor { 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; } @@ -701,13 +710,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) { 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", ] From e01c5cd8637c32b1bdf9c80f776278eab3feae0b Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Tue, 23 Sep 2014 16:38:52 -0700 Subject: [PATCH 4/6] Differentiate clearly how child layers handle scroll events This allows the scroll handler to know if a child layer didn't handle an event or the scroll position of the child layer was simply unchanged. --- components/compositing/compositor.rs | 3 ++- components/compositing/events.rs | 38 +++++++++++++++++++--------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index e752bc37a84..cd8830f1c9d 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; @@ -766,7 +767,7 @@ impl IOCompositor { delta, cursor.as_f32(), window_size, - scene_scale) || scroll; + scene_scale) == ScrollPositionChanged; } None => { } } diff --git a/components/compositing/events.rs b/components/compositing/events.rs index 0c9136d9936..ee1ba2231d4 100644 --- a/components/compositing/events.rs +++ b/components/compositing/events.rs @@ -39,6 +39,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,11 +55,11 @@ pub fn handle_scroll_event(layer: Rc>, cursor: TypedPoint2D, window_size: TypedSize2D, scale: ScaleFactor) - -> 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. @@ -61,13 +68,15 @@ pub fn handle_scroll_event(layer: Rc>, 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; + } } } @@ -81,7 +90,7 @@ pub fn clamp_scroll_offset_and_scroll_layer(layer: Rc>, new_offset: TypedPoint2D, window_size: TypedSize2D, scale: ScaleFactor) - -> bool { + -> ScrollEventResult { let layer_size = layer.bounds.borrow().size; 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); @@ -91,7 +100,7 @@ pub fn clamp_scroll_offset_and_scroll_layer(layer: Rc>, let new_offset_in_page_px = new_offset / scale; if layer.extra_data.borrow().scroll_offset == new_offset_in_page_px { - return false + return ScrollPositionUnchanged; } // The scroll offset is just a record of the scroll position of this scrolling root, @@ -102,7 +111,12 @@ pub fn clamp_scroll_offset_and_scroll_layer(layer: Rc>, for child in layer.children().iter() { result |= scroll_layer_and_all_child_layers(child.clone(), new_offset_in_page_px); } - return result; + + if result { + return ScrollPositionChanged; + } else { + return ScrollPositionUnchanged; + } } fn scroll_layer_and_all_child_layers(layer: Rc>, From f346a215f330343620c3a57c1edf8f1f91330d12 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Tue, 23 Sep 2014 16:46:13 -0700 Subject: [PATCH 5/6] Don't let base layers override root layer size Base layers (the background layer of each frame) shouldn't override the size of their root layers. This allows base layers to scroll inside root layer frames. This does mean that when determining the maximum scroll position, we need to look at the size of scrolling root children though. --- components/compositing/compositor.rs | 2 +- components/compositing/compositor_data.rs | 8 ++++++-- components/compositing/events.rs | 11 ++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index cd8830f1c9d..730db1519a3 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -500,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(), diff --git a/components/compositing/compositor_data.rs b/components/compositing/compositor_data.rs index 1abb88fbdb3..ad6bcefa8fd 100644 --- a/components/compositing/compositor_data.rs +++ b/components/compositing/compositor_data.rs @@ -72,14 +72,17 @@ impl CompositorData { tile_size, new_compositor_data)) } - pub fn update_layer(layer: Rc>, layer_properties: LayerProperties) { + pub fn update_layer_except_size(layer: Rc>, + 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_properties: LayerProperties) { let size: TypedSize2D = 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 @@ -89,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>, diff --git a/components/compositing/events.rs b/components/compositing/events.rs index ee1ba2231d4..a6b36fa6df0 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; @@ -86,12 +87,20 @@ pub fn handle_scroll_event(layer: Rc>, scale) } +pub fn calculate_content_size_for_layer(layer: Rc>) + -> TypedSize2D { + 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>, new_offset: TypedPoint2D, window_size: TypedSize2D, scale: ScaleFactor) -> ScrollEventResult { - let layer_size = layer.bounds.borrow().size; + 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 = From 65c6689bccdbde22030764adb2b563fcb0f847ca Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Tue, 23 Sep 2014 16:53:50 -0700 Subject: [PATCH 6/6] Compound scrolling offsets when setting content offset When traversing the layer tree to assign content offset, the new offset needs to take into account any additional offset from children that are also scrolling roots. This means that when you scroll a parent frame, it doesn't override the scroll position of its children, but adds to it. --- components/compositing/events.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/compositing/events.rs b/components/compositing/events.rs index a6b36fa6df0..aa1bfc6e2a3 100644 --- a/components/compositing/events.rs +++ b/components/compositing/events.rs @@ -143,8 +143,9 @@ fn scroll_layer_and_all_child_layers(layer: Rc>, 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;