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

Support for non-stacking-context scrolling areas #517

Merged
merged 1 commit into from Nov 4, 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

Support for non-stacking-context scrolling areas

When we encounter a stacking context which scrolls its contents, we
treat it as a special non-stacking-context scrolling area. All
scrolling areas with the same servo scroll root id will be scrolled in
tandem. Later changes will give these fake stacking contexts their own
display item.
  • Loading branch information
mrobinson committed Nov 4, 2016
commit d1c2258ab533ce8b45549b6af45f153a60e1381e
@@ -301,65 +301,86 @@ impl Frame {
None => return false,
};

let layer = self.layers.get_mut(&scroll_layer_id).unwrap();
if layer.scrolling.started_bouncing_back && phase == ScrollEventPhase::Move(false) {
return false
}
let scroll_root_id = match scroll_layer_id.info {
ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
ScrollLayerInfo::Fixed => unreachable!("Tried to scroll a fixed position layer."),

This comment has been minimized.

@kvark

kvark Nov 3, 2016

Member

should it do return false instead?

This comment has been minimized.

@glennw

glennw Nov 4, 2016

Member

I think in this case, get_scroll_layer is guaranteed to never return a position: fixed layer, so the unreachable!() is probably correct here.

This comment has been minimized.

@mrobinson

mrobinson Nov 4, 2016

Author Member

Yep, @glennw is correct here.

};

let overscroll_amount = layer.overscroll_amount();
let overscrolling = CAN_OVERSCROLL && (overscroll_amount.width != 0.0 ||
overscroll_amount.height != 0.0);
if overscrolling {
if overscroll_amount.width != 0.0 {
delta.x /= overscroll_amount.width.abs()
let mut scrolled_a_layer = false;
for (layer_id, layer) in self.layers.iter_mut() {

This comment has been minimized.

@kvark

kvark Nov 3, 2016

Member

can be rewritten as let scrolled_layer = match self.layers.find_mut(...) { Some(layer) => layer, None => return false };, followed by the code currently sitting in the for body. That would leave some code unchanged.

This comment has been minimized.

@mrobinson

mrobinson Nov 4, 2016

Author Member

Hrm. The issue here is that I want to scroll all layers that have the same scroll root id, instead of just the first one. Otherwise, perhaps I am misunderstanding your suggestion?

This comment has been minimized.

@glennw

glennw Nov 4, 2016

Member

I think it's fine as is - we'll land this as is, but feel free to file a follow up @kvark if we're misunderstanding what you mean.

if layer_id.pipeline_id != scroll_layer_id.pipeline_id {
continue;
}
if overscroll_amount.height != 0.0 {
delta.y /= overscroll_amount.height.abs()

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

if layer.scrolling.started_bouncing_back && phase == ScrollEventPhase::Move(false) {
continue;
}

let overscroll_amount = layer.overscroll_amount();
let overscrolling = CAN_OVERSCROLL && (overscroll_amount.width != 0.0 ||
overscroll_amount.height != 0.0);
if overscrolling {
if overscroll_amount.width != 0.0 {
delta.x /= overscroll_amount.width.abs()
}
if overscroll_amount.height != 0.0 {
delta.y /= overscroll_amount.height.abs()
}
}
}

let is_unscrollable = layer.content_size.width <= layer.local_viewport_rect.size.width &&
layer.content_size.height <= layer.local_viewport_rect.size.height;
let is_unscrollable =
layer.content_size.width <= layer.local_viewport_rect.size.width &&
layer.content_size.height <= layer.local_viewport_rect.size.height;

let original_layer_scroll_offset = layer.scrolling.offset;
let original_layer_scroll_offset = layer.scrolling.offset;

if layer.content_size.width > layer.local_viewport_rect.size.width {
layer.scrolling.offset.x = layer.scrolling.offset.x + delta.x;
if is_unscrollable || !CAN_OVERSCROLL {
layer.scrolling.offset.x = layer.scrolling.offset.x.min(0.0);
layer.scrolling.offset.x =
layer.scrolling.offset.x.max(-layer.content_size.width +
layer.local_viewport_rect.size.width);
if layer.content_size.width > layer.local_viewport_rect.size.width {
layer.scrolling.offset.x = layer.scrolling.offset.x + delta.x;
if is_unscrollable || !CAN_OVERSCROLL {
layer.scrolling.offset.x = layer.scrolling.offset.x.min(0.0);
layer.scrolling.offset.x =
layer.scrolling.offset.x.max(-layer.content_size.width +
layer.local_viewport_rect.size.width);
}
}
}

if layer.content_size.height > layer.local_viewport_rect.size.height {
layer.scrolling.offset.y = layer.scrolling.offset.y + delta.y;
if is_unscrollable || !CAN_OVERSCROLL {
layer.scrolling.offset.y = layer.scrolling.offset.y.min(0.0);
layer.scrolling.offset.y =
layer.scrolling.offset.y.max(-layer.content_size.height +
layer.local_viewport_rect.size.height);
if layer.content_size.height > layer.local_viewport_rect.size.height {
layer.scrolling.offset.y = layer.scrolling.offset.y + delta.y;
if is_unscrollable || !CAN_OVERSCROLL {
layer.scrolling.offset.y = layer.scrolling.offset.y.min(0.0);
layer.scrolling.offset.y =
layer.scrolling.offset.y.max(-layer.content_size.height +
layer.local_viewport_rect.size.height);
}
}
}

if phase == ScrollEventPhase::Start || phase == ScrollEventPhase::Move(true) {
layer.scrolling.started_bouncing_back = false
} else if overscrolling &&
((delta.x < 1.0 && delta.y < 1.0) || phase == ScrollEventPhase::End) {
layer.scrolling.started_bouncing_back = true;
layer.scrolling.bouncing_back = true
}
if phase == ScrollEventPhase::Start || phase == ScrollEventPhase::Move(true) {
layer.scrolling.started_bouncing_back = false
} else if overscrolling &&
((delta.x < 1.0 && delta.y < 1.0) || phase == ScrollEventPhase::End) {
layer.scrolling.started_bouncing_back = true;
layer.scrolling.bouncing_back = true
}

layer.scrolling.offset.x = layer.scrolling.offset.x.round();
layer.scrolling.offset.y = layer.scrolling.offset.y.round();
layer.scrolling.offset.x = layer.scrolling.offset.x.round();
layer.scrolling.offset.y = layer.scrolling.offset.y.round();

if CAN_OVERSCROLL {
layer.stretch_overscroll_spring();
if CAN_OVERSCROLL {
layer.stretch_overscroll_spring();
}

scrolled_a_layer = scrolled_a_layer ||
layer.scrolling.offset != original_layer_scroll_offset ||
layer.scrolling.started_bouncing_back;
}

layer.scrolling.offset != original_layer_scroll_offset || layer.scrolling
.started_bouncing_back
scrolled_a_layer
}

pub fn tick_scrolling_bounce_animations(&mut self) {
@@ -496,13 +517,26 @@ impl Frame {
}
}

// Build world space transform
let transform = parent_info.layer_relative_transform.pre_translated(stacking_context.bounds.origin.x,
stacking_context.bounds.origin.y,
0.0)
.pre_mul(&stacking_context.transform)
.pre_mul(&stacking_context.perspective);
// Stacking contexts with scroll roots are currently not "real" stacking contexts,
// but are currently represented as stacking contexts in the display list until they
// can get their own display item to represent them. Thus we do not adjust the transform
// to account for them and we expand the overflow region to include the area above
// their origin in the parent context.
let (transform, overflow) = if stacking_context.scroll_layer_id.is_none() {
(parent_info.layer_relative_transform.pre_translated(stacking_context.bounds.origin.x,
stacking_context.bounds.origin.y,

This comment has been minimized.

@glennw

glennw Nov 4, 2016

Member

nit: indentation

This comment has been minimized.

@mrobinson

mrobinson Nov 4, 2016

Author Member

Okay. Will fix this one.

0.0)
.pre_mul(&stacking_context.transform)
.pre_mul(&stacking_context.perspective),
stacking_context.overflow)
} else {
let mut overflow = stacking_context.overflow;
overflow.size.width += stacking_context.bounds.origin.x;
overflow.size.height += stacking_context.bounds.origin.y;
(parent_info.layer_relative_transform, overflow)
};

// Build world space transform
let scroll_layer_id = match (stacking_context.scroll_policy, stacking_context.scroll_layer_id) {
(ScrollPolicy::Fixed, _scroll_layer_id) => {
debug_assert!(_scroll_layer_id.is_none());
@@ -518,8 +552,8 @@ impl Frame {
};

// TODO(gw): Int with overflow etc
context.builder.push_layer(stacking_context.overflow,
stacking_context.overflow,
context.builder.push_layer(overflow,
overflow,
transform,
pipeline_id,
scroll_layer_id,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.