Skip to content

Commit 7ab5b4a

Browse files
author
Sam
committed
servo: Merge #14141 - Implement home end key scrolling (from samuknet:home-end-key-scroll2); r=glennw
<!-- Please describe your changes on the following line: --> * Refactor all scroll related code to use a new `ScrollLocation` struct which can either be a `delta` (as before) or a `Start` or `End` request, to represent the desire to scroll to the start and end of the page. Effectively, everywhere a delta was used, there is now a `ScrollLocation` struct instead. * Add key press listeners for HOME and END keys so as to cause a scroll to be queued with `ScrollLocation::Start` (in HOME case) or `ScrollLocation::End` (in END case). * These changes depend on added support for the new `ScrollLocation` in webrender and webrender_traits. See servo/webrender#540. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ x] These changes fix #13082 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests because scrolling I/O <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 1706ffd6e5a02f26f69970b3b41536a8a85ef6fe
1 parent c9391ab commit 7ab5b4a

File tree

9 files changed

+118
-47
lines changed

9 files changed

+118
-47
lines changed

servo/Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

servo/components/compositing/compositor.rs

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use style_traits::viewport::ViewportConstraints;
3939
use time::{precise_time_ns, precise_time_s};
4040
use touch::{TouchHandler, TouchAction};
4141
use webrender;
42-
use webrender_traits::{self, ScrollEventPhase, ServoScrollRootId, LayoutPoint};
42+
use webrender_traits::{self, ScrollEventPhase, ServoScrollRootId, LayoutPoint, ScrollLocation};
4343
use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg};
4444

4545
#[derive(Debug, PartialEq)]
@@ -227,8 +227,8 @@ pub struct IOCompositor<Window: WindowMethods> {
227227
struct ScrollZoomEvent {
228228
/// Change the pinch zoom level by this factor
229229
magnification: f32,
230-
/// Scroll by this offset
231-
delta: TypedPoint2D<f32, DevicePixel>,
230+
/// Scroll by this offset, or to Start or End
231+
scroll_location: ScrollLocation,
232232
/// Apply changes to the frame at this location
233233
cursor: TypedPoint2D<i32, DevicePixel>,
234234
/// The scroll event phase.
@@ -1027,15 +1027,19 @@ impl<Window: WindowMethods> IOCompositor<Window> {
10271027
match self.touch_handler.on_touch_move(identifier, point) {
10281028
TouchAction::Scroll(delta) => {
10291029
match point.cast() {
1030-
Some(point) => self.on_scroll_window_event(delta, point),
1030+
Some(point) => self.on_scroll_window_event(ScrollLocation::Delta(
1031+
webrender_traits::LayerPoint::from_untyped(
1032+
&delta.to_untyped())),
1033+
point),
10311034
None => error!("Point cast failed."),
10321035
}
10331036
}
10341037
TouchAction::Zoom(magnification, scroll_delta) => {
10351038
let cursor = TypedPoint2D::new(-1, -1); // Make sure this hits the base layer.
10361039
self.pending_scroll_zoom_events.push(ScrollZoomEvent {
10371040
magnification: magnification,
1038-
delta: scroll_delta,
1041+
scroll_location: ScrollLocation::Delta(webrender_traits::LayerPoint::from_untyped(
1042+
&scroll_delta.to_untyped())),
10391043
cursor: cursor,
10401044
phase: ScrollEventPhase::Move(true),
10411045
event_count: 1,
@@ -1096,7 +1100,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
10961100
}
10971101

10981102
fn on_scroll_window_event(&mut self,
1099-
delta: TypedPoint2D<f32, DevicePixel>,
1103+
scroll_location: ScrollLocation,
11001104
cursor: TypedPoint2D<i32, DevicePixel>) {
11011105
let event_phase = match (self.scroll_in_progress, self.in_scroll_transaction) {
11021106
(false, None) => ScrollEventPhase::Start,
@@ -1107,33 +1111,33 @@ impl<Window: WindowMethods> IOCompositor<Window> {
11071111
self.in_scroll_transaction = Some(Instant::now());
11081112
self.pending_scroll_zoom_events.push(ScrollZoomEvent {
11091113
magnification: 1.0,
1110-
delta: delta,
1114+
scroll_location: scroll_location,
11111115
cursor: cursor,
11121116
phase: event_phase,
11131117
event_count: 1,
11141118
});
11151119
}
11161120

11171121
fn on_scroll_start_window_event(&mut self,
1118-
delta: TypedPoint2D<f32, DevicePixel>,
1122+
scroll_location: ScrollLocation,
11191123
cursor: TypedPoint2D<i32, DevicePixel>) {
11201124
self.scroll_in_progress = true;
11211125
self.pending_scroll_zoom_events.push(ScrollZoomEvent {
11221126
magnification: 1.0,
1123-
delta: delta,
1127+
scroll_location: scroll_location,
11241128
cursor: cursor,
11251129
phase: ScrollEventPhase::Start,
11261130
event_count: 1,
11271131
});
11281132
}
11291133

11301134
fn on_scroll_end_window_event(&mut self,
1131-
delta: TypedPoint2D<f32, DevicePixel>,
1135+
scroll_location: ScrollLocation,
11321136
cursor: TypedPoint2D<i32, DevicePixel>) {
11331137
self.scroll_in_progress = false;
11341138
self.pending_scroll_zoom_events.push(ScrollZoomEvent {
11351139
magnification: 1.0,
1136-
delta: delta,
1140+
scroll_location: scroll_location,
11371141
cursor: cursor,
11381142
phase: ScrollEventPhase::End,
11391143
event_count: 1,
@@ -1146,14 +1150,34 @@ impl<Window: WindowMethods> IOCompositor<Window> {
11461150
// Batch up all scroll events into one, or else we'll do way too much painting.
11471151
let mut last_combined_event: Option<ScrollZoomEvent> = None;
11481152
for scroll_event in self.pending_scroll_zoom_events.drain(..) {
1149-
let this_delta = scroll_event.delta;
11501153
let this_cursor = scroll_event.cursor;
1154+
1155+
let this_delta = match scroll_event.scroll_location {
1156+
ScrollLocation::Delta(delta) => delta,
1157+
ScrollLocation::Start | ScrollLocation::End => {
1158+
// If this is an event which is scrolling to the start or end of the page,
1159+
// disregard other pending events and exit the loop.
1160+
last_combined_event = Some(scroll_event);
1161+
break;
1162+
}
1163+
};
1164+
11511165
if let Some(combined_event) = last_combined_event {
11521166
if combined_event.phase != scroll_event.phase {
1153-
let delta = (combined_event.delta / self.scale).to_untyped();
1167+
let combined_delta = match combined_event.scroll_location {
1168+
ScrollLocation::Delta(delta) => delta,
1169+
ScrollLocation::Start | ScrollLocation::End => {
1170+
// If this is an event which is scrolling to the start or end of the page,
1171+
// disregard other pending events and exit the loop.
1172+
last_combined_event = Some(scroll_event);
1173+
break;
1174+
}
1175+
};
1176+
let delta = (TypedPoint2D::from_untyped(&combined_delta.to_untyped()) / self.scale)
1177+
.to_untyped();
1178+
let delta = webrender_traits::LayerPoint::from_untyped(&delta);
11541179
let cursor =
11551180
(combined_event.cursor.to_f32() / self.scale).to_untyped();
1156-
let delta = webrender_traits::LayerPoint::from_untyped(&delta);
11571181
let location = webrender_traits::ScrollLocation::Delta(delta);
11581182
let cursor = webrender_traits::WorldPoint::from_untyped(&cursor);
11591183
self.webrender_api.scroll(location, cursor, combined_event.phase);
@@ -1165,7 +1189,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
11651189
(last_combined_event @ &mut None, _) => {
11661190
*last_combined_event = Some(ScrollZoomEvent {
11671191
magnification: scroll_event.magnification,
1168-
delta: this_delta,
1192+
scroll_location: ScrollLocation::Delta(webrender_traits::LayerPoint::from_untyped(
1193+
&this_delta.to_untyped())),
11691194
cursor: this_cursor,
11701195
phase: scroll_event.phase,
11711196
event_count: 1,
@@ -1177,30 +1202,41 @@ impl<Window: WindowMethods> IOCompositor<Window> {
11771202
// fling. This causes events to get bunched up occasionally, causing
11781203
// nasty-looking "pops". To mitigate this, during a fling we average
11791204
// deltas instead of summing them.
1180-
let old_event_count =
1181-
ScaleFactor::new(last_combined_event.event_count as f32);
1182-
last_combined_event.event_count += 1;
1183-
let new_event_count =
1184-
ScaleFactor::new(last_combined_event.event_count as f32);
1185-
last_combined_event.delta =
1186-
(last_combined_event.delta * old_event_count + this_delta) /
1187-
new_event_count;
1205+
if let ScrollLocation::Delta(delta) = last_combined_event.scroll_location {
1206+
let old_event_count =
1207+
ScaleFactor::new(last_combined_event.event_count as f32);
1208+
last_combined_event.event_count += 1;
1209+
let new_event_count =
1210+
ScaleFactor::new(last_combined_event.event_count as f32);
1211+
last_combined_event.scroll_location = ScrollLocation::Delta(
1212+
(delta * old_event_count + this_delta) /
1213+
new_event_count);
1214+
}
11881215
}
11891216
(&mut Some(ref mut last_combined_event), _) => {
1190-
last_combined_event.delta = last_combined_event.delta + this_delta;
1191-
last_combined_event.event_count += 1
1217+
if let ScrollLocation::Delta(delta) = last_combined_event.scroll_location {
1218+
last_combined_event.scroll_location = ScrollLocation::Delta(delta + this_delta);
1219+
last_combined_event.event_count += 1
1220+
}
11921221
}
11931222
}
11941223
}
11951224

11961225
// TODO(gw): Support zoom (WR issue #28).
11971226
if let Some(combined_event) = last_combined_event {
1198-
let delta = (combined_event.delta / self.scale).to_untyped();
1199-
let delta = webrender_traits::LayoutPoint::from_untyped(&delta);
1227+
let scroll_location = match combined_event.scroll_location {
1228+
ScrollLocation::Delta(delta) => {
1229+
let scaled_delta = (TypedPoint2D::from_untyped(&delta.to_untyped()) / self.scale)
1230+
.to_untyped();
1231+
let calculated_delta = webrender_traits::LayoutPoint::from_untyped(&scaled_delta);
1232+
ScrollLocation::Delta(calculated_delta)
1233+
},
1234+
// Leave ScrollLocation unchanged if it is Start or End location.
1235+
sl @ ScrollLocation::Start | sl @ ScrollLocation::End => sl,
1236+
};
12001237
let cursor = (combined_event.cursor.to_f32() / self.scale).to_untyped();
1201-
let location = webrender_traits::ScrollLocation::Delta(delta);
12021238
let cursor = webrender_traits::WorldPoint::from_untyped(&cursor);
1203-
self.webrender_api.scroll(location, cursor, combined_event.phase);
1239+
self.webrender_api.scroll(scroll_location, cursor, combined_event.phase);
12041240
self.waiting_for_results_of_scroll = true
12051241
}
12061242

@@ -1295,7 +1331,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
12951331
fn on_pinch_zoom_window_event(&mut self, magnification: f32) {
12961332
self.pending_scroll_zoom_events.push(ScrollZoomEvent {
12971333
magnification: magnification,
1298-
delta: TypedPoint2D::zero(), // TODO: Scroll to keep the center in view?
1334+
scroll_location: ScrollLocation::Delta(TypedPoint2D::zero()), // TODO: Scroll to keep the center in view?
12991335
cursor: TypedPoint2D::new(-1, -1), // Make sure this hits the base layer.
13001336
phase: ScrollEventPhase::Move(true),
13011337
event_count: 1,
@@ -1693,6 +1729,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
16931729
}
16941730
}
16951731

1732+
16961733
/// Why we performed a composite. This is used for debugging.
16971734
#[derive(Copy, Clone, PartialEq, Debug)]
16981735
pub enum CompositingReason {

servo/components/compositing/windowing.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use servo_geometry::ScreenPx;
1616
use servo_url::ServoUrl;
1717
use std::fmt::{Debug, Error, Formatter};
1818
use style_traits::cursor::Cursor;
19+
use webrender_traits::ScrollLocation;
1920

2021
#[derive(Clone)]
2122
pub enum MouseWindowEvent {
@@ -62,7 +63,7 @@ pub enum WindowEvent {
6263
Touch(TouchEventType, TouchId, TypedPoint2D<f32, DevicePixel>),
6364
/// Sent when the user scrolls. The first point is the delta and the second point is the
6465
/// origin.
65-
Scroll(TypedPoint2D<f32, DevicePixel>, TypedPoint2D<i32, DevicePixel>, TouchEventType),
66+
Scroll(ScrollLocation, TypedPoint2D<i32, DevicePixel>, TouchEventType),
6667
/// Sent when the user zooms.
6768
Zoom(f32),
6869
/// Simulated "pinch zoom" gesture for non-touch platforms (e.g. ctrl-scrollwheel).

servo/ports/cef/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ servo_geometry = {path = "../../components/geometry"}
3535
servo_url = {path = "../../components/url"}
3636
style_traits = {path = "../../components/style_traits"}
3737

38+
[dependencies.webrender_traits]
39+
git = "https://github.com/servo/webrender"
40+
default-features = false
41+
features = ["serde_derive", "ipc"]
42+
3843
[target.'cfg(target_os="macos")'.dependencies]
3944
objc = "0.2"
4045
cocoa = "0.5"

servo/ports/cef/browser_host.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use interfaces::{CefBrowser, CefBrowserHost, CefClient, cef_browser_t, cef_brows
88
use types::cef_event_flags_t::{EVENTFLAG_ALT_DOWN, EVENTFLAG_CONTROL_DOWN, EVENTFLAG_SHIFT_DOWN};
99
use types::cef_key_event_type_t::{KEYEVENT_CHAR, KEYEVENT_KEYDOWN, KEYEVENT_KEYUP, KEYEVENT_RAWKEYDOWN};
1010
use types::{cef_mouse_button_type_t, cef_mouse_event, cef_rect_t, cef_key_event, cef_window_handle_t};
11+
use webrender_traits::ScrollLocation;
1112
use wrappers::CefWrap;
1213

1314
use compositing::windowing::{WindowEvent, MouseWindowEvent};
@@ -471,7 +472,7 @@ full_cef_class_impl! {
471472
let delta_y: c_int = delta_y;
472473
let delta = TypedPoint2D::new(delta_x as f32, delta_y as f32);
473474
let origin = TypedPoint2D::new((*event).x as i32, (*event).y as i32);
474-
this.downcast().send_window_event(WindowEvent::Scroll(delta,
475+
this.downcast().send_window_event(WindowEvent::Scroll(ScrollLocation::Delta(delta),
475476
origin,
476477
TouchEventType::Move))
477478
}}

servo/ports/cef/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ extern crate style_traits;
2828

2929
extern crate net_traits;
3030
extern crate msg;
31+
extern crate webrender_traits;
3132

3233
extern crate libc;
3334

servo/ports/glutin/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ servo_config = {path = "../../components/config"}
2323
servo_url = {path = "../../components/url"}
2424
style_traits = {path = "../../components/style_traits"}
2525

26+
[dependencies.webrender_traits]
27+
git = "https://github.com/servo/webrender"
28+
default_features = false
29+
2630
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
2731
osmesa-sys = "0.1.2"
2832

servo/ports/glutin/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ extern crate servo_config;
2222
extern crate servo_geometry;
2323
extern crate servo_url;
2424
extern crate style_traits;
25+
extern crate webrender_traits;
26+
2527
#[cfg(target_os = "windows")] extern crate winapi;
2628
#[cfg(target_os = "windows")] extern crate user32;
2729
#[cfg(target_os = "windows")] extern crate gdi32;

0 commit comments

Comments
 (0)