From 2113e548196d89617820f6b63966ddb7b9fae316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20W=C3=BClker?= Date: Tue, 18 Mar 2025 10:35:24 +0100 Subject: [PATCH] Set composed flag for mouse events dispatched by the UA (#36010) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add doc comments to mouse event methods Signed-off-by: Simon Wülker * Make MouseEvents composed by default Signed-off-by: Simon Wülker --------- Signed-off-by: Simon Wülker --- components/script/dom/document.rs | 42 ++--------- components/script/dom/mouseevent.rs | 110 +++++++++++++++++++++++----- 2 files changed, 98 insertions(+), 54 deletions(-) diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index dc53e50d65f..c089dfbe951 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -1284,14 +1284,9 @@ impl Document { return; }; - let mouse_event_type_string = match event.action { - MouseButtonAction::Click => "click".to_owned(), - MouseButtonAction::Up => "mouseup".to_owned(), - MouseButtonAction::Down => "mousedown".to_owned(), - }; debug!( - "{}: at {:?}", - mouse_event_type_string, hit_test_result.point_in_viewport + "{:?}: at {:?}", + event.action, hit_test_result.point_in_viewport ); let node = unsafe { node::from_untrusted_compositor_node_address(hit_test_result.node) }; @@ -1304,7 +1299,7 @@ impl Document { }; let node = el.upcast::(); - debug!("{} on {:?}", mouse_event_type_string, node.debug_str()); + debug!("{:?} on {:?}", event.action, node.debug_str()); // Prevent click event if form control element is disabled. if let MouseButtonAction::Click = event.action { // The click event is filtered by the disabled state. @@ -1316,35 +1311,14 @@ impl Document { self.request_focus(Some(&*el), FocusType::Element, can_gc); } - // https://w3c.github.io/uievents/#event-type-click - let client_x = hit_test_result.point_in_viewport.x as i32; - let client_y = hit_test_result.point_in_viewport.y as i32; - let click_count = 1; - let dom_event = MouseEvent::new( - &self.window, - DOMString::from(mouse_event_type_string), - EventBubbles::Bubbles, - EventCancelable::Cancelable, - Some(&self.window), - click_count, - client_x, - client_y, - client_x, - client_y, // TODO: Get real screen coordinates? - false, - false, - false, - false, - event.button.into(), + let dom_event = DomRoot::upcast::(MouseEvent::for_platform_mouse_event( + event, pressed_mouse_buttons, - None, - Some(hit_test_result.point_relative_to_item), + &self.window, + &hit_test_result, can_gc, - ); - let dom_event = dom_event.upcast::(); + )); - // https://w3c.github.io/uievents/#trusted-events - dom_event.set_trusted(true); // https://html.spec.whatwg.org/multipage/#run-authentic-click-activation-steps let activatable = el.as_maybe_activatable(); match event.action { diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs index 2e769972ab2..71792fcec2b 100644 --- a/components/script/dom/mouseevent.rs +++ b/components/script/dom/mouseevent.rs @@ -9,6 +9,7 @@ use dom_struct::dom_struct; use euclid::default::Point2D; use js::rust::HandleObject; use servo_config::pref; +use webrender_traits::CompositorHitTestResult; use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods; use crate::dom::bindings::codegen::Bindings::MouseEventBinding; @@ -26,25 +27,49 @@ use crate::dom::uievent::UIEvent; use crate::dom::window::Window; use crate::script_runtime::CanGc; +/// #[dom_struct] pub(crate) struct MouseEvent { uievent: UIEvent, + + /// screen_x: Cell, + + /// screen_y: Cell, + + /// client_x: Cell, + + /// client_y: Cell, + page_x: Cell, page_y: Cell, x: Cell, y: Cell, offset_x: Cell, offset_y: Cell, + + /// ctrl_key: Cell, + + /// shift_key: Cell, + + /// alt_key: Cell, + + /// meta_key: Cell, + + /// button: Cell, + + /// buttons: Cell, + + /// related_target: MutNullableDom, #[no_trace] point_in_target: Cell>>, @@ -237,10 +262,55 @@ impl MouseEvent { pub(crate) fn point_in_target(&self) -> Option> { self.point_in_target.get() } + + /// Create a [MouseEvent] triggered by the embedder + pub(crate) fn for_platform_mouse_event( + event: embedder_traits::MouseButtonEvent, + pressed_mouse_buttons: u16, + window: &Window, + hit_test_result: &CompositorHitTestResult, + can_gc: CanGc, + ) -> DomRoot { + let mouse_event_type_string = match event.action { + embedder_traits::MouseButtonAction::Click => "click", + embedder_traits::MouseButtonAction::Up => "mouseup", + embedder_traits::MouseButtonAction::Down => "mousedown", + }; + + let client_x = hit_test_result.point_in_viewport.x as i32; + let client_y = hit_test_result.point_in_viewport.y as i32; + let click_count = 1; + let mouse_event = MouseEvent::new( + window, + mouse_event_type_string.into(), + EventBubbles::Bubbles, + EventCancelable::Cancelable, + Some(window), + click_count, + client_x, + client_y, + client_x, + client_y, // TODO: Get real screen coordinates? + false, + false, + false, + false, + event.button.into(), + pressed_mouse_buttons, + None, + Some(hit_test_result.point_relative_to_item), + can_gc, + ); + + mouse_event.upcast::().set_trusted(true); + mouse_event.upcast::().set_composed(true); + + mouse_event + } } impl MouseEventMethods for MouseEvent { - // https://w3c.github.io/uievents/#dom-mouseevent-mouseevent + /// fn Constructor( window: &Window, proto: Option, @@ -275,27 +345,27 @@ impl MouseEventMethods for MouseEvent { Ok(event) } - // https://w3c.github.io/uievents/#widl-MouseEvent-screenX + /// fn ScreenX(&self) -> i32 { self.screen_x.get() } - // https://w3c.github.io/uievents/#widl-MouseEvent-screenY + /// fn ScreenY(&self) -> i32 { self.screen_y.get() } - // https://w3c.github.io/uievents/#widl-MouseEvent-clientX + /// fn ClientX(&self) -> i32 { self.client_x.get() } - // https://w3c.github.io/uievents/#widl-MouseEvent-clientY + /// fn ClientY(&self) -> i32 { self.client_y.get() } - // https://drafts.csswg.org/cssom-view/#dom-mouseevent-pagex + /// fn PageX(&self) -> i32 { if self.upcast::().dispatching() { self.page_x.get() @@ -306,7 +376,7 @@ impl MouseEventMethods for MouseEvent { } } - // https://drafts.csswg.org/cssom-view/#dom-mouseevent-pagey + /// fn PageY(&self) -> i32 { if self.upcast::().dispatching() { self.page_y.get() @@ -317,17 +387,17 @@ impl MouseEventMethods for MouseEvent { } } - // https://drafts.csswg.org/cssom-view/#dom-mouseevent-x + /// fn X(&self) -> i32 { self.client_x.get() } - // https://drafts.csswg.org/cssom-view/#dom-mouseevent-y + /// fn Y(&self) -> i32 { self.client_y.get() } - // https://drafts.csswg.org/cssom-view/#dom-mouseevent-offsetx + /// fn OffsetX(&self, can_gc: CanGc) -> i32 { let event = self.upcast::(); if event.dispatching() { @@ -347,7 +417,7 @@ impl MouseEventMethods for MouseEvent { } } - // https://drafts.csswg.org/cssom-view/#dom-mouseevent-offsety + /// fn OffsetY(&self, can_gc: CanGc) -> i32 { let event = self.upcast::(); if event.dispatching() { @@ -367,37 +437,37 @@ impl MouseEventMethods for MouseEvent { } } - // https://w3c.github.io/uievents/#widl-MouseEvent-ctrlKey + /// fn CtrlKey(&self) -> bool { self.ctrl_key.get() } - // https://w3c.github.io/uievents/#widl-MouseEvent-shiftKey + /// fn ShiftKey(&self) -> bool { self.shift_key.get() } - // https://w3c.github.io/uievents/#widl-MouseEvent-altKey + /// fn AltKey(&self) -> bool { self.alt_key.get() } - // https://w3c.github.io/uievents/#widl-MouseEvent-metaKey + /// fn MetaKey(&self) -> bool { self.meta_key.get() } - // https://w3c.github.io/uievents/#widl-MouseEvent-button + /// fn Button(&self) -> i16 { self.button.get() } - // https://w3c.github.io/uievents/#dom-mouseevent-buttons + /// fn Buttons(&self) -> u16 { self.buttons.get() } - // https://w3c.github.io/uievents/#widl-MouseEvent-relatedTarget + /// fn GetRelatedTarget(&self) -> Option> { self.related_target.get() } @@ -415,7 +485,7 @@ impl MouseEventMethods for MouseEvent { } } - // https://w3c.github.io/uievents/#widl-MouseEvent-initMouseEvent + /// fn InitMouseEvent( &self, type_arg: DOMString, @@ -457,7 +527,7 @@ impl MouseEventMethods for MouseEvent { self.related_target.set(related_target_arg); } - // https://dom.spec.whatwg.org/#dom-event-istrusted + /// fn IsTrusted(&self) -> bool { self.uievent.IsTrusted() }