script: Pass more information to the MouseEvent constructor (#37672)

- Instead of eagerly computing `pageX` and `pageY`, collect the offset
  from the content's initial containing block in the compositor and pass
  that information through to `MouseEvent`. This prevents a layout flush
  that was happening when eagerly trying to fetch `Document` scroll
  offsets.
- Pass keyboard modifiers properly to `MouseEvent`.
- Now all this information is stored and passed as `Point2D` (typed) and
  `Modifiers` which greatly reduces the amount of arguments that need to
  be passed around.

Testing: It is difficult to test input events as they require WebDriver
which
isn't completely working yet. I have manually run Speedometer 2.1 and I
have
verified that this fixes the regression from #37601.
Fixes: #37601.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-06-25 14:29:27 +02:00 committed by GitHub
parent 50cf01cf3d
commit 0346a62214
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 374 additions and 369 deletions

View file

@ -49,9 +49,9 @@ use devtools_traits::{
};
use embedder_traits::user_content_manager::UserContentManager;
use embedder_traits::{
CompositorHitTestResult, EmbedderMsg, FocusSequenceNumber, InputEvent,
JavaScriptEvaluationError, JavaScriptEvaluationId, MediaSessionActionType, MouseButton,
MouseButtonAction, MouseButtonEvent, Theme, ViewportDetails, WebDriverScriptCommand,
EmbedderMsg, FocusSequenceNumber, InputEvent, JavaScriptEvaluationError,
JavaScriptEvaluationId, MediaSessionActionType, MouseButton, MouseButtonAction,
MouseButtonEvent, Theme, ViewportDetails, WebDriverScriptCommand,
};
use euclid::Point2D;
use euclid::default::Rect;
@ -1021,20 +1021,14 @@ impl ScriptThread {
fn process_mouse_move_event(
&self,
document: &Document,
hit_test_result: Option<CompositorHitTestResult>,
pressed_mouse_buttons: u16,
input_event: &ConstellationInputEvent,
can_gc: CanGc,
) {
// Get the previous target temporarily
let prev_mouse_over_target = self.topmost_mouse_over_target.get();
unsafe {
document.handle_mouse_move_event(
hit_test_result,
pressed_mouse_buttons,
&self.topmost_mouse_over_target,
can_gc,
)
document.handle_mouse_move_event(input_event, &self.topmost_mouse_over_target, can_gc)
}
// Short-circuit if nothing changed
@ -1109,29 +1103,15 @@ impl ScriptThread {
match event.event {
InputEvent::MouseButton(mouse_button_event) => {
document.handle_mouse_button_event(
mouse_button_event,
event.hit_test_result,
event.pressed_mouse_buttons,
can_gc,
);
document.handle_mouse_button_event(mouse_button_event, &event, can_gc);
},
InputEvent::MouseMove(_) => {
// The event itself is unecessary here, because the point in the viewport is in the hit test.
self.process_mouse_move_event(
&document,
event.hit_test_result,
event.pressed_mouse_buttons,
can_gc,
);
self.process_mouse_move_event(&document, &event, can_gc);
},
InputEvent::MouseLeave(_) => {
self.topmost_mouse_over_target.take();
document.handle_mouse_leave_event(
event.hit_test_result,
event.pressed_mouse_buttons,
can_gc,
);
document.handle_mouse_leave_event(&event, can_gc);
},
InputEvent::Touch(touch_event) => {
let touch_result =