web browser (Servo)
git clone https://git.lucas.co/cce-browser.git
Fix wheel scrolling: pass winit-signed deltas, drop manual scroll event
Servo turns a Wheel input event into scrolling internally — it hit-tests,
lets the page preventDefault, then applies the *inverted* WheelDelta as
the scroll (paint's webview_renderer). So the embedder must pass deltas
in winit sign convention (positive y = scroll up), exactly as cce-ui
delivers them. The previous code negated the delta (scrolling up at the
top of every page = visible no-op) and sent a redundant
notify_scroll_event.
Live-verified via ccectl injection: wheel scroll, PageDown, URL-bar
click/typing/Enter navigation, in-page link click, back button.
Co-Authored-By: Claude Fable 5 <[email protected]>
src/main.rs | 9 +++++----
src/webview.rs | 23 +++++++++--------------
2 files changed, 14 insertions(+), 18 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index 26cb670..c0a97ce 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -380,11 +380,12 @@ impl Application for BrowserApp {
if pos.y < CHROME_H {
return;
}
- // cce-ui deltas are winit-signed (positive = scroll up); the DOM and
- // Servo's Scroll::Delta want positive = reveal content below.
+ // WheelDelta keeps cce-ui's winit sign convention (positive = scroll
+ // up); Servo inverts it into the scroll offset internally, after the
+ // page has had its preventDefault chance.
let (dx, dy) = match delta {
- MouseScrollDelta::LineDelta(x, y) => (-(*x as f64) * LINE_PX, -(*y as f64) * LINE_PX),
- MouseScrollDelta::PixelDelta(p) => (-p.x, -p.y),
+ MouseScrollDelta::LineDelta(x, y) => (*x as f64 * LINE_PX, *y as f64 * LINE_PX),
+ MouseScrollDelta::PixelDelta(p) => (p.x, p.y),
};
let s = self.scale;
self.host.wheel(
diff --git a/src/webview.rs b/src/webview.rs
index 985c347..c565f08 100644
--- a/src/webview.rs
+++ b/src/webview.rs
@@ -14,11 +14,10 @@ use std::rc::Rc;
use dpi::PhysicalSize;
use euclid::Scale;
use servo::{
- DeviceIntRect, DevicePoint, DeviceVector2D, EventLoopWaker, InputEvent, Key as DomKey,
- KeyState, KeyboardEvent, LoadStatus, MouseButton as DomMouseButton, MouseButtonAction,
- MouseButtonEvent, MouseMoveEvent, RenderingContext, Scroll, Servo, ServoBuilder,
- SoftwareRenderingContext, WebView, WebViewBuilder, WebViewDelegate, WheelDelta, WheelEvent,
- WheelMode,
+ DeviceIntRect, DevicePoint, EventLoopWaker, InputEvent, Key as DomKey, KeyState,
+ KeyboardEvent, LoadStatus, MouseButton as DomMouseButton, MouseButtonAction, MouseButtonEvent,
+ MouseMoveEvent, RenderingContext, Servo, ServoBuilder, SoftwareRenderingContext, WebView,
+ WebViewBuilder, WebViewDelegate, WheelDelta, WheelEvent, WheelMode,
};
use url::Url;
@@ -207,19 +206,15 @@ impl ServoHost {
)));
}
- /// Wheel/scroll in device pixels, DOM sign convention (positive y
- /// reveals content below). Sends both the DOM wheel event and the
- /// compositor scroll.
+ /// Wheel in device pixels, winit sign convention (positive y = scroll
+ /// up). Servo hit-tests the wheel event, lets the page preventDefault,
+ /// and applies the inverted delta as the scroll itself — no separate
+ /// scroll event wanted.
pub fn wheel(&self, dx_px: f64, dy_px: f64, x_px: f32, y_px: f32) {
- let point = DevicePoint::new(x_px, y_px);
let _ = self.webview.notify_input_event(InputEvent::Wheel(WheelEvent::new(
WheelDelta { x: dx_px, y: dy_px, z: 0.0, mode: WheelMode::DeltaPixel },
- point.into(),
+ DevicePoint::new(x_px, y_px).into(),
)));
- self.webview.notify_scroll_event(
- Scroll::Delta(DeviceVector2D::new(dx_px as f32, dy_px as f32).into()),
- point.into(),
- );
}
pub fn key(&self, key: DomKey, pressed: bool) {