diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index d605f87a29..18f62a70db 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -19,7 +19,7 @@ use tiling::{AuxiliaryListsMap, FrameBuilder, FrameBuilderConfig, PrimitiveFlags use util::MatrixHelpers; use webrender_traits::{AuxiliaryLists, PipelineId, Epoch, ScrollPolicy, ScrollLayerId}; use webrender_traits::{ClipRegion, ColorF, DisplayItem, StackingContext, FilterOp, MixBlendMode}; -use webrender_traits::{ScrollEventPhase, ScrollLayerInfo, SpecificDisplayItem, ScrollLayerState}; +use webrender_traits::{ScrollEventPhase, ScrollLayerInfo, ScrollLocation, SpecificDisplayItem, ScrollLayerState}; use webrender_traits::{LayerRect, LayerPoint, LayerSize}; use webrender_traits::{ServoScrollRootId, ScrollLayerRect, as_scroll_parent_rect, ScrollLayerPixel}; use webrender_traits::WorldPoint4D; @@ -331,7 +331,7 @@ impl Frame { /// Returns true if any layers actually changed position or false otherwise. pub fn scroll(&mut self, - mut delta: Point2D, + scroll_location: ScrollLocation, cursor: Point2D, phase: ScrollEventPhase) -> bool { @@ -366,6 +366,33 @@ impl Frame { continue; } + let mut delta = match scroll_location { + ScrollLocation::Delta(delta) => delta, + ScrollLocation::Start => { + if layer.scrolling.offset.y.round() <= 0.0 { + // Nothing to do on this layer. + continue; + } + + layer.scrolling.offset.y = 0.0; + scrolled_a_layer = true; + continue; + }, + ScrollLocation::End => { + let end_pos = layer.local_viewport_rect.size.height + - layer.content_size.height; + + if layer.scrolling.offset.y.round() >= end_pos { + // Nothing to do on this layer. + continue; + } + + layer.scrolling.offset.y = end_pos; + scrolled_a_layer = true; + continue; + } + }; + let overscroll_amount = layer.overscroll_amount(); let overscrolling = CAN_OVERSCROLL && (overscroll_amount.width != 0.0 || overscroll_amount.height != 0.0); diff --git a/webrender_traits/src/api.rs b/webrender_traits/src/api.rs index 79f89ae75b..0168c94b5f 100644 --- a/webrender_traits/src/api.rs +++ b/webrender_traits/src/api.rs @@ -9,7 +9,7 @@ use offscreen_gl_context::{GLContextAttributes, GLLimits}; use std::cell::Cell; use {ApiMsg, ColorF, DisplayListBuilder, Epoch}; use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId}; -use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState, ServoScrollRootId}; +use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState, ScrollLocation, ServoScrollRootId}; use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand}; impl RenderApiSender { @@ -188,8 +188,8 @@ impl RenderApi { /// /// Webrender looks for the layer closest to the user /// which has `ScrollPolicy::Scrollable` set. - pub fn scroll(&self, delta: Point2D, cursor: Point2D, phase: ScrollEventPhase) { - let msg = ApiMsg::Scroll(delta, cursor, phase); + pub fn scroll(&self, scroll_location: ScrollLocation, cursor: Point2D, phase: ScrollEventPhase) { + let msg = ApiMsg::Scroll(scroll_location, cursor, phase); self.api_sender.send(msg).unwrap(); } diff --git a/webrender_traits/src/types.rs b/webrender_traits/src/types.rs index 7db1883e74..79fda1cfb2 100644 --- a/webrender_traits/src/types.rs +++ b/webrender_traits/src/types.rs @@ -48,7 +48,7 @@ pub enum ApiMsg { BuiltDisplayListDescriptor, AuxiliaryListsDescriptor), SetRootPipeline(PipelineId), - Scroll(Point2D, Point2D, ScrollEventPhase), + Scroll(ScrollLocation, Point2D, ScrollEventPhase), ScrollLayersWithScrollId(Point2D, PipelineId, ServoScrollRootId), TickScrollingBounce, TranslatePointToLayerSpace(Point2D, MsgSender<(Point2D, PipelineId)>), @@ -492,6 +492,16 @@ pub enum ScrollPolicy { Fixed, } +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +pub enum ScrollLocation { + /// Scroll by a certain amount. + Delta(Point2D), + /// Scroll to very top of element. + Start, + /// Scroll to very bottom of element. + End +} + #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct ServoScrollRootId(pub usize);