diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 79a74db93c7..81a17b5dfda 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -44,7 +44,7 @@ use style_traits::CSSPixel; use webrender::{CaptureBits, RenderApi, Transaction}; use webrender_api::units::{ DeviceIntPoint, DeviceIntRect, DevicePixel, DevicePoint, DeviceRect, LayoutPoint, LayoutRect, - LayoutSize, LayoutVector2D, WorldPoint, + LayoutSize, WorldPoint, }; use webrender_api::{ self, BuiltDisplayList, DirtyRect, DisplayListPayload, DocumentId, Epoch as WebRenderEpoch, @@ -714,11 +714,9 @@ impl IOCompositor { // is inverted compared to `winit`s wheel delta. Hence, // here we invert the sign to mimic wheel scroll // implementation in `headed_window.rs`. - let dx = -dx; - let dy = -dy; let delta = WheelDelta { - x: dx, - y: dy, + x: -dx, + y: -dy, z: 0.0, mode: WheelMode::DeltaPixel, }; @@ -768,7 +766,7 @@ impl IOCompositor { txn.set_scroll_offsets( external_scroll_id, vec![SampledScrollOffset { - offset: -offset, + offset, generation: 0, }], ); @@ -1169,7 +1167,6 @@ impl IOCompositor { continue; }; - let offset = LayoutVector2D::new(-offset.x, -offset.y); transaction.set_scroll_offsets( external_id, vec![SampledScrollOffset { @@ -1731,11 +1728,10 @@ impl IOCompositor { self.send_root_pipeline_display_list_in_transaction(&mut transaction); } for update in scroll_offset_updates { - let offset = LayoutVector2D::new(-update.offset.x, -update.offset.y); transaction.set_scroll_offsets( update.external_scroll_id, vec![SampledScrollOffset { - offset, + offset: update.offset, generation: 0, }], ); diff --git a/components/compositing/touch.rs b/components/compositing/touch.rs index 1fe8d14817d..357ca48d70e 100644 --- a/components/compositing/touch.rs +++ b/components/compositing/touch.rs @@ -406,7 +406,9 @@ impl TouchHandler { *velocity /= 2.0; // update the touch point every time when panning. touch_sequence.active_touch_points[idx].point = point; - TouchMoveAction::Scroll(delta, point) + + // Scroll offsets are opposite to the direction of finger motion. + TouchMoveAction::Scroll(-delta, point) } else if delta.x.abs() > TOUCH_PAN_MIN_SCREEN_PX || delta.y.abs() > TOUCH_PAN_MIN_SCREEN_PX { @@ -417,7 +419,9 @@ impl TouchHandler { touch_sequence.prevent_click = true; // update the touch point touch_sequence.active_touch_points[idx].point = point; - TouchMoveAction::Scroll(delta, point) + + // Scroll offsets are opposite to the direction of finger motion. + TouchMoveAction::Scroll(-delta, point) } else { // We don't update the touchpoint, so multiple small moves can // accumulate and merge into a larger move. @@ -435,8 +439,11 @@ impl TouchHandler { touch_sequence.active_touch_points[idx].point = point; let (d1, c1) = touch_sequence.pinch_distance_and_center(); let magnification = d1 / d0; + let scroll_delta = c1 - c0 * Scale::new(magnification); - TouchMoveAction::Zoom(magnification, scroll_delta) + + // Scroll offsets are opposite to the direction of finger motion. + TouchMoveAction::Zoom(magnification, -scroll_delta) } else { // We don't update the touchpoint, so multiple small moves can // accumulate and merge into a larger move. diff --git a/components/compositing/webview_renderer.rs b/components/compositing/webview_renderer.rs index 2f0575837fe..d810e3286fb 100644 --- a/components/compositing/webview_renderer.rs +++ b/components/compositing/webview_renderer.rs @@ -339,7 +339,7 @@ impl WebViewRenderer { pub(crate) fn on_vsync(&mut self) { if let Some(fling_action) = self.touch_handler.on_vsync() { self.on_scroll_window_event( - ScrollLocation::Delta(fling_action.delta), + ScrollLocation::Delta(-fling_action.delta), fling_action.cursor, ); } diff --git a/components/layout/layout_impl.rs b/components/layout/layout_impl.rs index cd0e84e3710..cac6ec75b04 100644 --- a/components/layout/layout_impl.rs +++ b/components/layout/layout_impl.rs @@ -476,7 +476,6 @@ impl Layout for LayoutThread { .borrow_mut() .as_mut() .and_then(|tree| tree.compositor_info.scroll_tree.scroll_offset(id)) - .map(|scroll_offset| -scroll_offset) } } @@ -1083,7 +1082,7 @@ impl LayoutThread { .scroll_tree .set_scroll_offset_for_node_with_external_scroll_id( external_scroll_id, - -offset, + offset, ScrollType::Script, ) { diff --git a/components/servo/webview.rs b/components/servo/webview.rs index 9fbc21b46f0..f71f31634a9 100644 --- a/components/servo/webview.rs +++ b/components/servo/webview.rs @@ -434,6 +434,8 @@ impl WebView { )) } + /// Ask the [`WebView`] to scroll web content. Note that positive scroll offsets reveal more + /// content on the bottom and right of the page. pub fn notify_scroll_event(&self, location: ScrollLocation, point: DeviceIntPoint) { self.inner() .compositor diff --git a/components/shared/compositing/display_list.rs b/components/shared/compositing/display_list.rs index c426f58a85c..60692a9d913 100644 --- a/components/shared/compositing/display_list.rs +++ b/components/shared/compositing/display_list.rs @@ -130,11 +130,11 @@ impl ScrollableNodeInfo { let original_layer_scroll_offset = self.offset; if scrollable_size.width > 0. && self.scroll_sensitivity.x.contains(context) { - self.offset.x = new_offset.x.min(0.0).max(-scrollable_size.width); + self.offset.x = new_offset.x.clamp(0.0, scrollable_size.width); } if scrollable_size.height > 0. && self.scroll_sensitivity.y.contains(context) { - self.offset.y = new_offset.y.min(0.0).max(-scrollable_size.height); + self.offset.y = new_offset.y.clamp(0.0, scrollable_size.height); } if self.offset != original_layer_scroll_offset { @@ -158,7 +158,7 @@ impl ScrollableNodeInfo { let delta = match scroll_location { ScrollLocation::Delta(delta) => delta, ScrollLocation::Start => { - if self.offset.y.round() >= 0.0 { + if self.offset.y.round() <= 0.0 { // Nothing to do on this layer. return None; } @@ -167,8 +167,8 @@ impl ScrollableNodeInfo { return Some(self.offset); }, ScrollLocation::End => { - let end_pos = -self.scrollable_size().height; - if self.offset.y.round() <= end_pos { + let end_pos = self.scrollable_size().height; + if self.offset.y.round() >= end_pos { // Nothing to do on this layer. return None; } @@ -231,20 +231,9 @@ impl ScrollTreeNode { /// Set the offset for this node, returns false if this was a /// non-scrolling node for which you cannot set the offset. - pub fn set_offset(&mut self, new_offset: LayoutVector2D) -> bool { - match self.info { - SpatialTreeNodeInfo::Scroll(ref mut info) => { - let scrollable_size = info.scrollable_size(); - if scrollable_size.width > 0. { - info.offset.x = (new_offset.x).min(0.0).max(-scrollable_size.width); - } - - if scrollable_size.height > 0. { - info.offset.y = (new_offset.y).min(0.0).max(-scrollable_size.height); - } - true - }, - _ => false, + pub fn set_offset(&mut self, new_offset: LayoutVector2D) { + if let SpatialTreeNodeInfo::Scroll(ref mut info) = self.info { + info.scroll_to_offset(new_offset, ScrollType::Script); } } diff --git a/components/shared/compositing/tests/compositor.rs b/components/shared/compositing/tests/compositor.rs index a061d467086..157b51be3a8 100644 --- a/components/shared/compositing/tests/compositor.rs +++ b/components/shared/compositing/tests/compositor.rs @@ -46,11 +46,11 @@ fn test_scroll_tree_simple_scroll() { let (scrolled_id, offset) = scroll_tree .scroll_node_or_ancestor( &id, - ScrollLocation::Delta(LayoutVector2D::new(-20.0, -40.0)), + ScrollLocation::Delta(LayoutVector2D::new(20.0, 40.0)), ScrollType::Script, ) .unwrap(); - let expected_offset = LayoutVector2D::new(-20.0, -40.0); + let expected_offset = LayoutVector2D::new(20.0, 40.0); assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id)); assert_eq!(offset, expected_offset); assert_eq!(scroll_tree.get_node(&id).offset(), Some(expected_offset)); @@ -58,7 +58,7 @@ fn test_scroll_tree_simple_scroll() { let (scrolled_id, offset) = scroll_tree .scroll_node_or_ancestor( &id, - ScrollLocation::Delta(LayoutVector2D::new(20.0, 40.0)), + ScrollLocation::Delta(LayoutVector2D::new(-20.0, -40.0)), ScrollType::Script, ) .unwrap(); @@ -67,10 +67,10 @@ fn test_scroll_tree_simple_scroll() { assert_eq!(offset, expected_offset); assert_eq!(scroll_tree.get_node(&id).offset(), Some(expected_offset)); - // Scroll offsets must be negative. + // Scroll offsets must be positive. let result = scroll_tree.scroll_node_or_ancestor( &id, - ScrollLocation::Delta(LayoutVector2D::new(20.0, 40.0)), + ScrollLocation::Delta(LayoutVector2D::new(-20.0, -40.0)), ScrollType::Script, ); assert!(result.is_none()); @@ -99,11 +99,11 @@ fn test_scroll_tree_simple_scroll_chaining() { let (scrolled_id, offset) = scroll_tree .scroll_node_or_ancestor( &unscrollable_child_id, - ScrollLocation::Delta(LayoutVector2D::new(-20.0, -40.0)), + ScrollLocation::Delta(LayoutVector2D::new(20.0, 40.0)), ScrollType::Script, ) .unwrap(); - let expected_offset = LayoutVector2D::new(-20.0, -40.0); + let expected_offset = LayoutVector2D::new(20.0, 40.0); assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id)); assert_eq!(offset, expected_offset); assert_eq!( @@ -114,11 +114,11 @@ fn test_scroll_tree_simple_scroll_chaining() { let (scrolled_id, offset) = scroll_tree .scroll_node_or_ancestor( &unscrollable_child_id, - ScrollLocation::Delta(LayoutVector2D::new(-10.0, -15.0)), + ScrollLocation::Delta(LayoutVector2D::new(10.0, 15.0)), ScrollType::Script, ) .unwrap(); - let expected_offset = LayoutVector2D::new(-30.0, -55.0); + let expected_offset = LayoutVector2D::new(30.0, 55.0); assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id)); assert_eq!(offset, expected_offset); assert_eq!( @@ -140,7 +140,7 @@ fn test_scroll_tree_chain_when_at_extent() { .scroll_node_or_ancestor(&child_id, ScrollLocation::End, ScrollType::Script) .unwrap(); - let expected_offset = LayoutVector2D::new(0.0, -100.0); + let expected_offset = LayoutVector2D::new(0.0, 100.0); assert_eq!(scrolled_id, ExternalScrollId(1, pipeline_id)); assert_eq!(offset, expected_offset); assert_eq!( @@ -153,11 +153,11 @@ fn test_scroll_tree_chain_when_at_extent() { let (scrolled_id, offset) = scroll_tree .scroll_node_or_ancestor( &child_id, - ScrollLocation::Delta(LayoutVector2D::new(0.0, -10.0)), + ScrollLocation::Delta(LayoutVector2D::new(0.0, 10.0)), ScrollType::Script, ) .unwrap(); - let expected_offset = LayoutVector2D::new(0.0, -10.0); + let expected_offset = LayoutVector2D::new(0.0, 10.0); assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id)); assert_eq!(offset, expected_offset); assert_eq!( @@ -187,11 +187,11 @@ fn test_scroll_tree_chain_through_overflow_hidden() { let (scrolled_id, offset) = scroll_tree .scroll_node_or_ancestor( &overflow_hidden_id, - ScrollLocation::Delta(LayoutVector2D::new(-20.0, -40.0)), + ScrollLocation::Delta(LayoutVector2D::new(20.0, 40.0)), ScrollType::InputEvents, ) .unwrap(); - let expected_offset = LayoutVector2D::new(-20.0, -40.0); + let expected_offset = LayoutVector2D::new(20.0, 40.0); assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id)); assert_eq!(offset, expected_offset); assert_eq!( diff --git a/ports/servoshell/desktop/app_state.rs b/ports/servoshell/desktop/app_state.rs index bad4ea4eaa8..db6a0a7f0c8 100644 --- a/ports/servoshell/desktop/app_state.rs +++ b/ports/servoshell/desktop/app_state.rs @@ -361,14 +361,14 @@ impl RunningAppState { .shortcut(Modifiers::empty(), Key::PageDown, || { let scroll_location = ScrollLocation::Delta(Vector2D::new( 0.0, - -self.inner().window.page_height() + 2.0 * LINE_HEIGHT, + self.inner().window.page_height() - 2.0 * LINE_HEIGHT, )); webview.notify_scroll_event(scroll_location, origin); }) .shortcut(Modifiers::empty(), Key::PageUp, || { let scroll_location = ScrollLocation::Delta(Vector2D::new( 0.0, - self.inner().window.page_height() - 2.0 * LINE_HEIGHT, + -self.inner().window.page_height() + 2.0 * LINE_HEIGHT, )); webview.notify_scroll_event(scroll_location, origin); }) @@ -379,19 +379,19 @@ impl RunningAppState { webview.notify_scroll_event(ScrollLocation::End, origin); }) .shortcut(Modifiers::empty(), Key::ArrowUp, || { - let location = ScrollLocation::Delta(Vector2D::new(0.0, 3.0 * LINE_HEIGHT)); - webview.notify_scroll_event(location, origin); - }) - .shortcut(Modifiers::empty(), Key::ArrowDown, || { let location = ScrollLocation::Delta(Vector2D::new(0.0, -3.0 * LINE_HEIGHT)); webview.notify_scroll_event(location, origin); }) + .shortcut(Modifiers::empty(), Key::ArrowDown, || { + let location = ScrollLocation::Delta(Vector2D::new(0.0, 3.0 * LINE_HEIGHT)); + webview.notify_scroll_event(location, origin); + }) .shortcut(Modifiers::empty(), Key::ArrowLeft, || { - let location = ScrollLocation::Delta(Vector2D::new(LINE_HEIGHT, 0.0)); + let location = ScrollLocation::Delta(Vector2D::new(-LINE_HEIGHT, 0.0)); webview.notify_scroll_event(location, origin); }) .shortcut(Modifiers::empty(), Key::ArrowRight, || { - let location = ScrollLocation::Delta(Vector2D::new(-LINE_HEIGHT, 0.0)); + let location = ScrollLocation::Delta(Vector2D::new(LINE_HEIGHT, 0.0)); webview.notify_scroll_event(location, origin); }); } diff --git a/ports/servoshell/desktop/headed_window.rs b/ports/servoshell/desktop/headed_window.rs index 3769a43629c..341b8c12e67 100644 --- a/ports/servoshell/desktop/headed_window.rs +++ b/ports/servoshell/desktop/headed_window.rs @@ -630,10 +630,9 @@ impl WindowPortsMethods for Window { dy = 0.0; } - let scroll_location = ScrollLocation::Delta(Vector2D::new(dx as f32, dy as f32)); - // Send events webview.notify_input_event(InputEvent::Wheel(WheelEvent::new(delta, point))); + let scroll_location = ScrollLocation::Delta(-Vector2D::new(dx as f32, dy as f32)); webview.notify_scroll_event(scroll_location, point.to_i32()); }, WindowEvent::Touch(touch) => { diff --git a/ports/servoshell/egl/android.rs b/ports/servoshell/egl/android.rs index 5a3047c8542..88cc05a6ed9 100644 --- a/ports/servoshell/egl/android.rs +++ b/ports/servoshell/egl/android.rs @@ -244,32 +244,6 @@ pub extern "C" fn Java_org_servo_servoview_JNIServo_goForward<'local>( call(&mut env, |s| s.go_forward()); } -#[unsafe(no_mangle)] -pub extern "C" fn Java_org_servo_servoview_JNIServo_scrollStart<'local>( - mut env: JNIEnv<'local>, - _: JClass<'local>, - dx: jint, - dy: jint, - x: jint, - y: jint, -) { - debug!("scrollStart"); - call(&mut env, |s| s.scroll_start(dx as f32, dy as f32, x, y)); -} - -#[unsafe(no_mangle)] -pub extern "C" fn Java_org_servo_servoview_JNIServo_scrollEnd<'local>( - mut env: JNIEnv<'local>, - _: JClass<'local>, - dx: jint, - dy: jint, - x: jint, - y: jint, -) { - debug!("scrollEnd"); - call(&mut env, |s| s.scroll_end(dx as f32, dy as f32, x, y)); -} - #[unsafe(no_mangle)] pub extern "C" fn Java_org_servo_servoview_JNIServo_scroll<'local>( mut env: JNIEnv<'local>, diff --git a/ports/servoshell/egl/app_state.rs b/ports/servoshell/egl/app_state.rs index e767e1a8c2b..11ba656d7fc 100644 --- a/ports/servoshell/egl/app_state.rs +++ b/ports/servoshell/egl/app_state.rs @@ -474,18 +474,6 @@ impl RunningAppState { self.perform_updates(); } - /// Start scrolling. - /// x/y are scroll coordinates. - /// dx/dy are scroll deltas. - #[cfg(not(target_env = "ohos"))] - pub fn scroll_start(&self, dx: f32, dy: f32, x: i32, y: i32) { - let delta = Vector2D::new(dx, dy); - let scroll_location = ScrollLocation::Delta(delta); - self.active_webview() - .notify_scroll_event(scroll_location, Point2D::new(x, y)); - self.perform_updates(); - } - /// Scroll. /// x/y are scroll coordinates. /// dx/dy are scroll deltas. @@ -497,18 +485,6 @@ impl RunningAppState { self.perform_updates(); } - /// End scrolling. - /// x/y are scroll coordinates. - /// dx/dy are scroll deltas. - #[cfg(not(target_env = "ohos"))] - pub fn scroll_end(&self, dx: f32, dy: f32, x: i32, y: i32) { - let delta = Vector2D::new(dx, dy); - let scroll_location = ScrollLocation::Delta(delta); - self.active_webview() - .notify_scroll_event(scroll_location, Point2D::new(x, y)); - self.perform_updates(); - } - /// Touch event: press down pub fn touch_down(&self, x: f32, y: f32, pointer_id: i32) { self.active_webview() diff --git a/support/android/apk/servoview/src/main/java/org/servo/servoview/JNIServo.java b/support/android/apk/servoview/src/main/java/org/servo/servoview/JNIServo.java index 131c1410b2c..5b2e13ddd24 100644 --- a/support/android/apk/servoview/src/main/java/org/servo/servoview/JNIServo.java +++ b/support/android/apk/servoview/src/main/java/org/servo/servoview/JNIServo.java @@ -41,12 +41,8 @@ public class JNIServo { public native void loadUri(String uri); - public native void scrollStart(int dx, int dy, int x, int y); - public native void scroll(int dx, int dy, int x, int y); - public native void scrollEnd(int dx, int dy, int x, int y); - public native void touchDown(float x, float y, int pointer_id); public native void touchMove(float x, float y, int pointer_id); diff --git a/support/android/apk/servoview/src/main/java/org/servo/servoview/Servo.java b/support/android/apk/servoview/src/main/java/org/servo/servoview/Servo.java index 9687278c0bf..399dfea31e6 100644 --- a/support/android/apk/servoview/src/main/java/org/servo/servoview/Servo.java +++ b/support/android/apk/servoview/src/main/java/org/servo/servoview/Servo.java @@ -107,18 +107,10 @@ public class Servo { mRunCallback.inGLThread(() -> mJNI.loadUri(uri)); } - public void scrollStart(int dx, int dy, int x, int y) { - mRunCallback.inGLThread(() -> mJNI.scrollStart(dx, dy, x, y)); - } - public void scroll(int dx, int dy, int x, int y) { mRunCallback.inGLThread(() -> mJNI.scroll(dx, dy, x, y)); } - public void scrollEnd(int dx, int dy, int x, int y) { - mRunCallback.inGLThread(() -> mJNI.scrollEnd(dx, dy, x, y)); - } - public void touchDown(float x, float y, int pointerId) { mRunCallback.inGLThread(() -> mJNI.touchDown(x, y, pointerId)); } diff --git a/support/android/apk/servoview/src/main/java/org/servo/servoview/ServoView.java b/support/android/apk/servoview/src/main/java/org/servo/servoview/ServoView.java index 5001f910ed4..7a8d0c9cd6f 100644 --- a/support/android/apk/servoview/src/main/java/org/servo/servoview/ServoView.java +++ b/support/android/apk/servoview/src/main/java/org/servo/servoview/ServoView.java @@ -143,7 +143,7 @@ public class ServoView extends SurfaceView if (mFlinging && mScroller.isFinished()) { mFlinging = false; - mServo.scrollEnd(0, 0, mCurX, mCurY); + mServo.scroll(0, 0, -mCurX, -mCurY); } if (mFlinging) { @@ -172,7 +172,7 @@ public class ServoView extends SurfaceView int x = Math.min(mCurX, this.getHeight()); int y = Math.min(mCurY, this.getWidth()); - mServo.scroll(dx, dy, x, y); + mServo.scroll(-dx, -dy, x, y); } if (zoomNecessary) { @@ -229,18 +229,10 @@ public class ServoView extends SurfaceView } } - public void scrollStart(int dx, int dy, int x, int y) { - mServo.scrollStart(dx, dy, x, y); - } - public void scroll(int dx, int dy, int x, int y) { mServo.scroll(dx, dy, x, y); } - public void scrollEnd(int dx, int dy, int x, int y) { - mServo.scrollEnd(dx, dy, x, y); - } - public void click(float x, float y) { mServo.click(x, y); } @@ -257,7 +249,7 @@ public class ServoView extends SurfaceView mCurY = velocityY < 0 ? mPageHeight : 0; mLastY = mCurY; mScroller.fling(mCurX, mCurY, (int) velocityX, (int) velocityY, 0, mPageWidth, 0, mPageHeight); - mServo.scrollStart(0, 0, mCurX, mCurY); + mServo.scroll(0, 0, mCurX, mCurY); startLooping(); return true; } @@ -309,7 +301,7 @@ public class ServoView extends SurfaceView } public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - mServo.scroll((int) -distanceX, (int) -distanceY, (int) e2.getX(), (int) e2.getY()); + mServo.scroll((int) distanceX, (int) distanceY, (int) e2.getX(), (int) e2.getY()); return true; }