mirror of
https://github.com/servo/servo.git
synced 2025-07-19 05:13:55 +01:00
script: Ensure that keyboard modifiers, screen point, and client point are set in WheelEvents (#37947)
- Updating the WheelEvent initialization to correctly handle keyboard modifiers when the wheel event is triggered. The changes ensure that the modifiers (Ctrl, Alt, Shift, Meta) are properly set based on the current state of the keyboard when the wheel event is created. This is particularly important for scenarios where the wheel event is influenced by key presses, such as scrolling with the Ctrl key pressed to zoom in or out. - Updating the `screen_point` and `client_point` as it was always 0,0 before. Now, it shows the correct position of the mouse pointer while triggering the wheel event. Test: Manual Test case and existing WPT tests (classic/perform_actions/wheel.py[test_scroll_with_key_pressed]) Fixes: #37827 Signed-off-by: abdelrahman1234567 <abdelrahman.hossameldin.awadalla@huawei.com>
This commit is contained in:
parent
f70a4eb4ff
commit
c76c44d0fb
5 changed files with 129 additions and 17 deletions
|
@ -2186,11 +2186,11 @@ impl Document {
|
||||||
pub(crate) fn handle_wheel_event(
|
pub(crate) fn handle_wheel_event(
|
||||||
&self,
|
&self,
|
||||||
event: WheelEvent,
|
event: WheelEvent,
|
||||||
hit_test_result: Option<CompositorHitTestResult>,
|
input_event: &ConstellationInputEvent,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
// Ignore all incoming events without a hit test.
|
// Ignore all incoming events without a hit test.
|
||||||
let Some(hit_test_result) = hit_test_result else {
|
let Some(hit_test_result) = &input_event.hit_test_result else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2220,6 +2220,16 @@ impl Document {
|
||||||
EventCancelable::Cancelable,
|
EventCancelable::Cancelable,
|
||||||
Some(&self.window),
|
Some(&self.window),
|
||||||
0i32,
|
0i32,
|
||||||
|
hit_test_result.point_in_viewport.to_i32(),
|
||||||
|
hit_test_result.point_in_viewport.to_i32(),
|
||||||
|
hit_test_result
|
||||||
|
.point_relative_to_initial_containing_block
|
||||||
|
.to_i32(),
|
||||||
|
input_event.active_keyboard_modifiers,
|
||||||
|
0i16,
|
||||||
|
input_event.pressed_mouse_buttons,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
// winit defines positive wheel delta values as revealing more content left/up.
|
// winit defines positive wheel delta values as revealing more content left/up.
|
||||||
// https://docs.rs/winit-gtk/latest/winit/event/enum.MouseScrollDelta.html
|
// https://docs.rs/winit-gtk/latest/winit/event/enum.MouseScrollDelta.html
|
||||||
// This is the opposite of wheel delta in uievents
|
// This is the opposite of wheel delta in uievents
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
use euclid::Point2D;
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
|
use keyboard_types::Modifiers;
|
||||||
|
use style_traits::CSSPixel;
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
|
use crate::dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::WheelEventBinding;
|
use crate::dom::bindings::codegen::Bindings::WheelEventBinding;
|
||||||
|
@ -17,6 +20,7 @@ use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::mouseevent::MouseEvent;
|
use crate::dom::mouseevent::MouseEvent;
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use crate::script_runtime::CanGc;
|
use crate::script_runtime::CanGc;
|
||||||
|
@ -57,6 +61,14 @@ impl WheelEvent {
|
||||||
cancelable: EventCancelable,
|
cancelable: EventCancelable,
|
||||||
view: Option<&Window>,
|
view: Option<&Window>,
|
||||||
detail: i32,
|
detail: i32,
|
||||||
|
screen_point: Point2D<i32, CSSPixel>,
|
||||||
|
client_point: Point2D<i32, CSSPixel>,
|
||||||
|
page_point: Point2D<i32, CSSPixel>,
|
||||||
|
modifiers: Modifiers,
|
||||||
|
button: i16,
|
||||||
|
buttons: u16,
|
||||||
|
related_target: Option<&EventTarget>,
|
||||||
|
point_in_target: Option<Point2D<f32, CSSPixel>>,
|
||||||
delta_x: Finite<f64>,
|
delta_x: Finite<f64>,
|
||||||
delta_y: Finite<f64>,
|
delta_y: Finite<f64>,
|
||||||
delta_z: Finite<f64>,
|
delta_z: Finite<f64>,
|
||||||
|
@ -64,8 +76,26 @@ impl WheelEvent {
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<WheelEvent> {
|
) -> DomRoot<WheelEvent> {
|
||||||
Self::new_with_proto(
|
Self::new_with_proto(
|
||||||
window, None, type_, can_bubble, cancelable, view, detail, delta_x, delta_y, delta_z,
|
window,
|
||||||
delta_mode, can_gc,
|
None,
|
||||||
|
type_,
|
||||||
|
can_bubble,
|
||||||
|
cancelable,
|
||||||
|
view,
|
||||||
|
detail,
|
||||||
|
screen_point,
|
||||||
|
client_point,
|
||||||
|
page_point,
|
||||||
|
modifiers,
|
||||||
|
button,
|
||||||
|
buttons,
|
||||||
|
related_target,
|
||||||
|
point_in_target,
|
||||||
|
delta_x,
|
||||||
|
delta_y,
|
||||||
|
delta_z,
|
||||||
|
delta_mode,
|
||||||
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +108,14 @@ impl WheelEvent {
|
||||||
cancelable: EventCancelable,
|
cancelable: EventCancelable,
|
||||||
view: Option<&Window>,
|
view: Option<&Window>,
|
||||||
detail: i32,
|
detail: i32,
|
||||||
|
screen_point: Point2D<i32, CSSPixel>,
|
||||||
|
client_point: Point2D<i32, CSSPixel>,
|
||||||
|
page_point: Point2D<i32, CSSPixel>,
|
||||||
|
modifiers: Modifiers,
|
||||||
|
button: i16,
|
||||||
|
buttons: u16,
|
||||||
|
related_target: Option<&EventTarget>,
|
||||||
|
point_in_target: Option<Point2D<f32, CSSPixel>>,
|
||||||
delta_x: Finite<f64>,
|
delta_x: Finite<f64>,
|
||||||
delta_y: Finite<f64>,
|
delta_y: Finite<f64>,
|
||||||
delta_z: Finite<f64>,
|
delta_z: Finite<f64>,
|
||||||
|
@ -85,21 +123,74 @@ impl WheelEvent {
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<WheelEvent> {
|
) -> DomRoot<WheelEvent> {
|
||||||
let ev = WheelEvent::new_unintialized(window, proto, can_gc);
|
let ev = WheelEvent::new_unintialized(window, proto, can_gc);
|
||||||
ev.InitWheelEvent(
|
ev.intitialize_wheel_event(
|
||||||
type_,
|
type_,
|
||||||
bool::from(can_bubble),
|
can_bubble,
|
||||||
bool::from(cancelable),
|
cancelable,
|
||||||
view,
|
view,
|
||||||
detail,
|
detail,
|
||||||
|
screen_point,
|
||||||
|
client_point,
|
||||||
|
page_point,
|
||||||
|
modifiers,
|
||||||
|
button,
|
||||||
|
buttons,
|
||||||
|
related_target,
|
||||||
|
point_in_target,
|
||||||
delta_x,
|
delta_x,
|
||||||
delta_y,
|
delta_y,
|
||||||
delta_z,
|
delta_z,
|
||||||
delta_mode,
|
delta_mode,
|
||||||
can_gc,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
ev
|
ev
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub(crate) fn intitialize_wheel_event(
|
||||||
|
&self,
|
||||||
|
type_: DOMString,
|
||||||
|
can_bubble: EventBubbles,
|
||||||
|
cancelable: EventCancelable,
|
||||||
|
view: Option<&Window>,
|
||||||
|
detail: i32,
|
||||||
|
screen_point: Point2D<i32, CSSPixel>,
|
||||||
|
client_point: Point2D<i32, CSSPixel>,
|
||||||
|
page_point: Point2D<i32, CSSPixel>,
|
||||||
|
modifiers: Modifiers,
|
||||||
|
button: i16,
|
||||||
|
buttons: u16,
|
||||||
|
related_target: Option<&EventTarget>,
|
||||||
|
point_in_target: Option<Point2D<f32, CSSPixel>>,
|
||||||
|
delta_x: Finite<f64>,
|
||||||
|
delta_y: Finite<f64>,
|
||||||
|
delta_z: Finite<f64>,
|
||||||
|
delta_mode: u32,
|
||||||
|
) {
|
||||||
|
if self.upcast::<Event>().dispatching() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.upcast::<MouseEvent>().initialize_mouse_event(
|
||||||
|
type_,
|
||||||
|
can_bubble,
|
||||||
|
cancelable,
|
||||||
|
view,
|
||||||
|
detail,
|
||||||
|
screen_point,
|
||||||
|
client_point,
|
||||||
|
page_point,
|
||||||
|
modifiers,
|
||||||
|
button,
|
||||||
|
buttons,
|
||||||
|
related_target,
|
||||||
|
point_in_target,
|
||||||
|
);
|
||||||
|
self.delta_x.set(delta_x);
|
||||||
|
self.delta_y.set(delta_y);
|
||||||
|
self.delta_z.set(delta_z);
|
||||||
|
self.delta_mode.set(delta_mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WheelEventMethods<crate::DomTypeHolder> for WheelEvent {
|
impl WheelEventMethods<crate::DomTypeHolder> for WheelEvent {
|
||||||
|
@ -111,14 +202,31 @@ impl WheelEventMethods<crate::DomTypeHolder> for WheelEvent {
|
||||||
type_: DOMString,
|
type_: DOMString,
|
||||||
init: &WheelEventBinding::WheelEventInit,
|
init: &WheelEventBinding::WheelEventInit,
|
||||||
) -> Fallible<DomRoot<WheelEvent>> {
|
) -> Fallible<DomRoot<WheelEvent>> {
|
||||||
|
let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles);
|
||||||
|
let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable);
|
||||||
|
let scroll_offset = window.scroll_offset(can_gc);
|
||||||
|
|
||||||
|
let page_point = Point2D::<i32, CSSPixel>::new(
|
||||||
|
scroll_offset.x as i32 + init.parent.clientX,
|
||||||
|
scroll_offset.y as i32 + init.parent.clientY,
|
||||||
|
);
|
||||||
|
|
||||||
let event = WheelEvent::new_with_proto(
|
let event = WheelEvent::new_with_proto(
|
||||||
window,
|
window,
|
||||||
proto,
|
proto,
|
||||||
type_,
|
type_,
|
||||||
EventBubbles::from(init.parent.parent.parent.parent.bubbles),
|
bubbles,
|
||||||
EventCancelable::from(init.parent.parent.parent.parent.cancelable),
|
cancelable,
|
||||||
init.parent.parent.parent.view.as_deref(),
|
init.parent.parent.parent.view.as_deref(),
|
||||||
init.parent.parent.parent.detail,
|
init.parent.parent.parent.detail,
|
||||||
|
Point2D::new(init.parent.screenX, init.parent.screenY),
|
||||||
|
Point2D::new(init.parent.clientX, init.parent.clientY),
|
||||||
|
Point2D::new(page_point.x, page_point.y),
|
||||||
|
init.parent.parent.modifiers(),
|
||||||
|
init.parent.button,
|
||||||
|
init.parent.buttons,
|
||||||
|
init.parent.relatedTarget.as_deref(),
|
||||||
|
None,
|
||||||
init.deltaX,
|
init.deltaX,
|
||||||
init.deltaY,
|
init.deltaY,
|
||||||
init.deltaZ,
|
init.deltaZ,
|
||||||
|
|
|
@ -1133,7 +1133,7 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
InputEvent::Wheel(wheel_event) => {
|
InputEvent::Wheel(wheel_event) => {
|
||||||
document.handle_wheel_event(wheel_event, event.hit_test_result, can_gc);
|
document.handle_wheel_event(wheel_event, &event, can_gc);
|
||||||
},
|
},
|
||||||
InputEvent::Keyboard(keyboard_event) => {
|
InputEvent::Keyboard(keyboard_event) => {
|
||||||
document.dispatch_key_event(keyboard_event, can_gc);
|
document.dispatch_key_event(keyboard_event, can_gc);
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
[Event-subclasses-constructors.html]
|
[Event-subclasses-constructors.html]
|
||||||
[WheelEvent constructor (argument with non-default values)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[KeyboardEvent constructor (argument with non-default values)]
|
[KeyboardEvent constructor (argument with non-default values)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
[test_scroll_shadow_tree[inner-closed\]]
|
[test_scroll_shadow_tree[inner-closed\]]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_scroll_with_key_pressed]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_scroll_shadow_tree[outer-open\]]
|
[test_scroll_shadow_tree[outer-open\]]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue