Implement wheel action in webdriver (#36744)

https://w3c.github.io/webdriver/#wheel-actions

Test:
`tests/wpt/tests/webdriver/tests/classic/perform_actions/wheel.py::{test_null_response_value,test_params_actions_origin_outside_viewport[element],test_params_actions_origin_outside_viewport[viewport]},
tests/wpt/tests/webdriver/tests/classic/perform_actions/perform.py`
Fixes: https://github.com/servo/servo/issues/36720

cc: @xiaochengh @longvatrong111 @yezhizhen

Signed-off-by: PotatoCP <kenzieradityatirtarahardja.18@gmail.com>
Co-authored-by: PotatoCP <kenzieradityatirtarahardja.18@gmail.com>
This commit is contained in:
Kenzie Raditya Tirtarahardja 2025-05-07 16:41:34 +08:00 committed by GitHub
parent f47e69c112
commit eaf9224799
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 255 additions and 51 deletions

View file

@ -26,9 +26,9 @@ use crossbeam_channel::{Receiver, Sender};
use dpi::PhysicalSize;
use embedder_traits::{
CompositorHitTestResult, Cursor, InputEvent, MouseButtonEvent, MouseMoveEvent, ShutdownState,
TouchEventType, UntrustedNodeAddress, ViewportDetails,
TouchEventType, UntrustedNodeAddress, ViewportDetails, WheelDelta, WheelEvent, WheelMode,
};
use euclid::{Point2D, Rect, Scale, Size2D, Transform3D};
use euclid::{Point2D, Rect, Scale, Size2D, Transform3D, Vector2D};
use fnv::FnvHashMap;
use ipc_channel::ipc::{self, IpcSharedMemory};
use libc::c_void;
@ -646,6 +646,26 @@ impl IOCompositor {
.dispatch_input_event(InputEvent::MouseMove(MouseMoveEvent { point }));
},
CompositorMsg::WebDriverWheelScrollEvent(webview_id, x, y, delta_x, delta_y) => {
let Some(webview_renderer) = self.webview_renderers.get_mut(webview_id) else {
warn!("Handling input event for unknown webview: {webview_id}");
return;
};
let delta = WheelDelta {
x: delta_x,
y: delta_y,
z: 0.0,
mode: WheelMode::DeltaPixel,
};
let dppx = webview_renderer.device_pixels_per_page_pixel();
let point = dppx.transform_point(Point2D::new(x, y));
let scroll_delta =
dppx.transform_vector(Vector2D::new(delta_x as f32, delta_y as f32));
webview_renderer
.dispatch_input_event(InputEvent::Wheel(WheelEvent { delta, point }));
webview_renderer.on_webdriver_wheel_action(scroll_delta, point);
},
CompositorMsg::SendInitialTransaction(pipeline) => {
let mut txn = Transaction::new();
txn.set_display_list(WebRenderEpoch(0), (pipeline, Default::default()));

View file

@ -42,6 +42,7 @@ mod from_constellation {
Self::LoadComplete(..) => target!("LoadComplete"),
Self::WebDriverMouseButtonEvent(..) => target!("WebDriverMouseButtonEvent"),
Self::WebDriverMouseMoveEvent(..) => target!("WebDriverMouseMoveEvent"),
Self::WebDriverWheelScrollEvent(..) => target!("WebDriverWheelScrollEvent"),
Self::SendInitialTransaction(..) => target!("SendInitialTransaction"),
Self::SendScrollNode(..) => target!("SendScrollNode"),
Self::SendDisplayList { .. } => target!("SendDisplayList"),

View file

@ -726,6 +726,22 @@ impl WebViewRenderer {
}));
}
/// Push scroll pending event when receiving wheel action from webdriver
pub(crate) fn on_webdriver_wheel_action(
&mut self,
scroll_delta: Vector2D<f32, DevicePixel>,
point: Point2D<f32, DevicePixel>,
) {
if self.global.borrow().shutdown_state() != ShutdownState::NotShuttingDown {
return;
}
let scroll_location =
ScrollLocation::Delta(LayoutVector2D::from_untyped(scroll_delta.to_untyped()));
let cursor = DeviceIntPoint::new(point.x as i32, point.y as i32);
self.on_scroll_window_event(scroll_location, cursor)
}
pub(crate) fn process_pending_scroll_events(&mut self, compositor: &mut IOCompositor) {
if self.pending_scroll_zoom_events.is_empty() {
return;