Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API for scrolling individual layers #590

Merged
merged 1 commit into from Nov 25, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Add API for scrolling individual layers

This will allow Servo to reimplement scroll_to_fragment.
  • Loading branch information
mrobinson committed Nov 25, 2016
commit c33d8e4056ffa863880dbb08b20ee439d56a8dbf
@@ -21,7 +21,7 @@ use webrender_traits::{AuxiliaryLists, PipelineId, Epoch, ScrollPolicy, ScrollLa
use webrender_traits::{ClipRegion, ColorF, DisplayItem, StackingContext, FilterOp, MixBlendMode};
use webrender_traits::{ScrollEventPhase, ScrollLayerInfo, SpecificDisplayItem, ScrollLayerState};
use webrender_traits::{LayerRect, LayerPoint, LayerSize};
use webrender_traits::{ScrollLayerRect, as_scroll_parent_rect, ScrollLayerPixel};
use webrender_traits::{ServoScrollRootId, ScrollLayerRect, as_scroll_parent_rect, ScrollLayerPixel};
use webrender_traits::WorldPoint4D;
use webrender_traits::{LayerTransform, LayerToScrollTransform, ScrollToWorldTransform};

@@ -52,6 +52,7 @@ pub struct Frame {
AuxiliaryLists,
BuildHasherDefault<FnvHasher>>,
pub root_scroll_layer_id: Option<ScrollLayerId>,
pending_scroll_offsets: HashMap<(PipelineId, ServoScrollRootId), LayerPoint>,
id: FrameId,
debug: bool,
frame_builder_config: FrameBuilderConfig,
@@ -210,6 +211,7 @@ impl Frame {
pipeline_auxiliary_lists: HashMap::with_hasher(Default::default()),
layers: HashMap::with_hasher(Default::default()),
root_scroll_layer_id: None,
pending_scroll_offsets: HashMap::new(),
id: FrameId(0),
debug: debug,
frame_builder: None,
@@ -295,6 +297,38 @@ impl Frame {
result
}

/// Returns true if any layers actually changed position or false otherwise.
pub fn scroll_layers(&mut self,
origin: Point2D<f32>,
pipeline_id: PipelineId,
scroll_root_id: ServoScrollRootId)
-> bool {
let origin = LayerPoint::new(origin.x.max(0.0), origin.y.max(0.0));

let mut scrolled_a_layer = false;
let mut found_layer = false;
for (layer_id, layer) in self.layers.iter_mut() {
if layer_id.pipeline_id != pipeline_id {
continue;
}

match layer_id.info {
ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
ScrollLayerInfo::Fixed => continue,
_ => {}
}

found_layer = true;
scrolled_a_layer |= layer.set_scroll_origin(&origin);
}

if !found_layer {
self.pending_scroll_offsets.insert((pipeline_id, scroll_root_id), origin);
}

scrolled_a_layer
}

/// Returns true if any layers actually changed position or false otherwise.
pub fn scroll(&mut self,
mut delta: Point2D<f32>,
@@ -480,6 +514,18 @@ impl Frame {
};

layer.finalize(&scrolling_state);

let scroll_root_id = match scroll_layer_id.info {
ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
_ => continue,
};


let pipeline_id = scroll_layer_id.pipeline_id;
if let Some(pending_offset) =
self.pending_scroll_offsets.get_mut(&(pipeline_id, scroll_root_id)) {
layer.set_scroll_origin(pending_offset);
}
}
}

@@ -86,6 +86,26 @@ impl Layer {
LayerSize::new(overscroll_x, overscroll_y)
}

pub fn set_scroll_origin(&mut self, origin: &LayerPoint) -> bool {
if self.content_size.width <= self.local_viewport_rect.size.width &&
self.content_size.height <= self.local_viewport_rect.size.height {
return false;
}

let new_offset = LayerPoint::new(
(-origin.x).max(-self.content_size.width + self.local_viewport_rect.size.width),
(-origin.y).max(-self.content_size.height + self.local_viewport_rect.size.height));
let new_offset = LayerPoint::new(new_offset.x.min(0.0).round(), new_offset.y.min(0.0).round());
if new_offset == self.scrolling.offset {
return false;
}

self.scrolling.offset = new_offset;
self.scrolling.bouncing_back = false;
self.scrolling.started_bouncing_back = false;
return true;
}

pub fn stretch_overscroll_spring(&mut self) {
let overscroll_amount = self.overscroll_amount();
self.scrolling.spring.coords(self.scrolling.offset,
@@ -246,6 +246,24 @@ impl RenderBackend {
None => self.notify_compositor_of_new_scroll_frame(false),
}
}
ApiMsg::ScrollLayersWithScrollId(origin, pipeline_id, scroll_root_id) => {
let frame = profile_counters.total_time.profile(|| {
if self.frame.scroll_layers(origin, pipeline_id, scroll_root_id) {
Some(self.render())
} else {
None
}
});

match frame {
Some(frame) => {
self.publish_frame(frame, &mut profile_counters);
self.notify_compositor_of_new_scroll_frame(true)
}
None => self.notify_compositor_of_new_scroll_frame(false),
}

}
ApiMsg::TickScrollingBounce => {
let frame = profile_counters.total_time.profile(|| {
self.frame.tick_scrolling_bounce_animations();
@@ -9,7 +9,7 @@ use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, Epoch};
use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState, ServoScrollRootId};
use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand};

impl RenderApiSender {
@@ -193,6 +193,14 @@ impl RenderApi {
self.api_sender.send(msg).unwrap();
}

pub fn scroll_layers_with_scroll_root_id(&self,
new_scroll_origin: Point2D<f32>,
pipeline_id: PipelineId,
scroll_root_id: ServoScrollRootId) {
let msg = ApiMsg::ScrollLayersWithScrollId(new_scroll_origin, pipeline_id, scroll_root_id);
self.api_sender.send(msg).unwrap();
}

pub fn tick_scrolling_bounce_animations(&self) {
let msg = ApiMsg::TickScrollingBounce;
self.api_sender.send(msg).unwrap();
@@ -49,6 +49,7 @@ pub enum ApiMsg {
AuxiliaryListsDescriptor),
SetRootPipeline(PipelineId),
Scroll(Point2D<f32>, Point2D<f32>, ScrollEventPhase),
ScrollLayersWithScrollId(Point2D<f32>, PipelineId, ServoScrollRootId),
TickScrollingBounce,
TranslatePointToLayerSpace(Point2D<f32>, MsgSender<(Point2D<f32>, PipelineId)>),
GetScrollLayerState(MsgSender<Vec<ScrollLayerState>>),
@@ -449,6 +450,13 @@ impl ScrollLayerId {
info: ScrollLayerInfo::Scrollable(0, ServoScrollRootId(0)),
}
}

pub fn scroll_root_id(&self) -> Option<ServoScrollRootId> {
match self.info {
ScrollLayerInfo::Scrollable(_, scroll_root_id) => Some(scroll_root_id),
ScrollLayerInfo::Fixed => None,
}
}
}

#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.