Auto merge of #9851 - pcwalton:overscroll, r=glennw

Implement support for overscrolling on the Mac.

Requires tomaka/glutin#734, servo/webrender_traits#14, and
servo/webrender#217.

r? whoever (waiting on the landing of the above)

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9851)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-03-15 00:18:05 +05:30
commit 881d6b4220
8 changed files with 152 additions and 49 deletions

View file

@ -53,7 +53,7 @@ use util::geometry::{PagePx, ScreenPx, ViewportPx};
use util::opts;
use util::print_tree::PrintTree;
use webrender;
use webrender_traits;
use webrender_traits::{self, ScrollEventPhase};
use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg};
#[derive(Debug, PartialEq)]
@ -196,6 +196,9 @@ pub struct IOCompositor<Window: WindowMethods> {
/// The id of the pipeline that was last sent a mouse move event, if any.
last_mouse_move_recipient: Option<PipelineId>,
/// Whether a scroll is in progress; i.e. whether the user's fingers are down.
scroll_in_progress: bool,
/// The webrender renderer, if enabled.
webrender: Option<webrender::Renderer>,
@ -203,6 +206,7 @@ pub struct IOCompositor<Window: WindowMethods> {
webrender_api: Option<webrender_traits::RenderApi>,
}
#[derive(Copy, Clone)]
pub struct ScrollZoomEvent {
/// Change the pinch zoom level by this factor
magnification: f32,
@ -210,6 +214,8 @@ pub struct ScrollZoomEvent {
delta: TypedPoint2D<DevicePixel, f32>,
/// Apply changes to the frame at this location
cursor: TypedPoint2D<DevicePixel, i32>,
/// The scroll event phase.
phase: ScrollEventPhase,
}
#[derive(PartialEq, Debug)]
@ -427,6 +433,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
surface_map: SurfaceMap::new(BUFFER_MAP_SIZE),
pending_subpages: HashSet::new(),
last_mouse_move_recipient: None,
scroll_in_progress: false,
webrender: state.webrender,
webrender_api: webrender_api,
}
@ -1184,8 +1191,16 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}
WindowEvent::Scroll(delta, cursor) => {
self.on_scroll_window_event(delta, cursor);
WindowEvent::Scroll(delta, cursor, phase) => {
match phase {
TouchEventType::Move => self.on_scroll_window_event(delta, cursor),
TouchEventType::Up | TouchEventType::Cancel => {
self.on_scroll_end_window_event(delta, cursor);
}
TouchEventType::Down => {
self.on_scroll_start_window_event(delta, cursor);
}
}
}
WindowEvent::Zoom(magnification) => {
@ -1368,6 +1383,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
magnification: magnification,
delta: scroll_delta,
cursor: cursor,
phase: ScrollEventPhase::Move(true),
});
self.composite_if_necessary(CompositingReason::Zoom);
}
@ -1421,8 +1437,34 @@ impl<Window: WindowMethods> IOCompositor<Window> {
magnification: 1.0,
delta: delta,
cursor: cursor,
phase: ScrollEventPhase::Move(self.scroll_in_progress),
});
self.composite_if_necessary(CompositingReason::Scroll);
}
fn on_scroll_start_window_event(&mut self,
delta: TypedPoint2D<DevicePixel, f32>,
cursor: TypedPoint2D<DevicePixel, i32>) {
self.scroll_in_progress = true;
self.pending_scroll_zoom_events.push(ScrollZoomEvent {
magnification: 1.0,
delta: delta,
cursor: cursor,
phase: ScrollEventPhase::Start,
});
self.composite_if_necessary(CompositingReason::Scroll);
}
fn on_scroll_end_window_event(&mut self,
delta: TypedPoint2D<DevicePixel, f32>,
cursor: TypedPoint2D<DevicePixel, i32>) {
self.scroll_in_progress = false;
self.pending_scroll_zoom_events.push(ScrollZoomEvent {
magnification: 1.0,
delta: delta,
cursor: cursor,
phase: ScrollEventPhase::End,
});
self.composite_if_necessary(CompositingReason::Scroll);
}
@ -1432,19 +1474,41 @@ impl<Window: WindowMethods> IOCompositor<Window> {
match self.webrender_api {
Some(ref webrender_api) => {
// Batch up all scroll events into one, or else we'll do way too much painting.
let mut total_delta = None;
let mut last_cursor = Point2D::zero();
let mut last_combined_event: Option<ScrollZoomEvent> = None;
for scroll_event in self.pending_scroll_zoom_events.drain(..) {
let this_delta = scroll_event.delta / self.scene.scale;
last_cursor = scroll_event.cursor.as_f32() / self.scene.scale;
match total_delta {
None => total_delta = Some(this_delta),
Some(ref mut total_delta) => *total_delta = *total_delta + this_delta,
let this_delta = scroll_event.delta;
let this_cursor = scroll_event.cursor;
if let Some(combined_event) = last_combined_event {
if combined_event.phase != scroll_event.phase {
webrender_api.scroll(
(combined_event.delta / self.scene.scale).to_untyped(),
(combined_event.cursor.as_f32() / self.scene.scale).to_untyped(),
combined_event.phase);
last_combined_event = None
}
}
match last_combined_event {
None => {
last_combined_event = Some(ScrollZoomEvent {
magnification: scroll_event.magnification,
delta: this_delta,
cursor: this_cursor,
phase: scroll_event.phase,
})
}
Some(ref mut last_combined_event) => {
last_combined_event.delta = last_combined_event.delta + this_delta;
}
}
}
// TODO(gw): Support zoom (WR issue #28).
if let Some(total_delta) = total_delta {
webrender_api.scroll(total_delta.to_untyped(), last_cursor.to_untyped());
if let Some(combined_event) = last_combined_event {
webrender_api.scroll(
(combined_event.delta / self.scene.scale).to_untyped(),
(combined_event.cursor.as_f32() / self.scene.scale).to_untyped(),
combined_event.phase);
}
}
None => {
@ -1617,6 +1681,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
magnification: magnification,
delta: Point2D::typed(0.0, 0.0), // TODO: Scroll to keep the center in view?
cursor: Point2D::typed(-1, -1), // Make sure this hits the base layer.
phase: ScrollEventPhase::Move(true),
});
self.composite_if_necessary(CompositingReason::Zoom);
}
@ -2016,6 +2081,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.composition_request = CompositionRequest::NoCompositingNecessary;
self.process_pending_scroll_events();
self.process_animations();
self.start_scrolling_bounce_if_necessary();
Ok(rv)
}
@ -2221,6 +2287,21 @@ impl<Window: WindowMethods> IOCompositor<Window> {
print_tree.add_item(layer_string);
}
}
fn start_scrolling_bounce_if_necessary(&mut self) {
if self.scroll_in_progress {
return
}
match self.webrender {
Some(ref webrender) if webrender.layers_are_bouncing_back() => {}
_ => return,
}
if let Some(ref webrender_api) = self.webrender_api {
webrender_api.tick_scrolling_bounce_animations()
}
}
}
fn find_layer_with_pipeline_and_layer_id_for_layer(layer: Rc<Layer<CompositorData>>,

View file

@ -63,7 +63,7 @@ pub enum WindowEvent {
Touch(TouchEventType, TouchId, TypedPoint2D<DevicePixel, f32>),
/// Sent when the user scrolls. The first point is the delta and the second point is the
/// origin.
Scroll(TypedPoint2D<DevicePixel, f32>, TypedPoint2D<DevicePixel, i32>),
Scroll(TypedPoint2D<DevicePixel, f32>, TypedPoint2D<DevicePixel, i32>, TouchEventType),
/// Sent when the user zooms.
Zoom(f32),
/// Simulated "pinch zoom" gesture for non-touch platforms (e.g. ctrl-scrollwheel).

View file

@ -788,7 +788,7 @@ dependencies = [
"net_traits 0.0.1",
"script_traits 0.0.1",
"servo-egl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-glutin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-glutin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"style_traits 0.0.1",
"url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
@ -1854,7 +1854,7 @@ dependencies = [
[[package]]
name = "servo-glutin"
version = "0.4.9"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"android_glue 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1896,7 +1896,7 @@ dependencies = [
"servo-egl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-fontconfig 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-freetype-sys 2.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-glutin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-glutin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2292,7 +2292,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.1.0"
source = "git+https://github.com/servo/webrender#38031eed57b2df8a57e4cff576e2b5b6f2cd8316"
source = "git+https://github.com/servo/webrender#9309d52279a73ea15f955424899fed9b9ab70c95"
dependencies = [
"app_units 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2313,7 +2313,7 @@ dependencies = [
[[package]]
name = "webrender_traits"
version = "0.1.0"
source = "git+https://github.com/servo/webrender_traits#94f16f55e65d735a9c1dc38733937cb2774322e1"
source = "git+https://github.com/servo/webrender_traits#a4d2e91915512c3d6b08d0d391221bb240d972d5"
dependencies = [
"app_units 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",