aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorAndrei Volykhin <andrei.volykhin@gmail.com>2025-04-02 14:20:25 +0300
committerGitHub <noreply@github.com>2025-04-02 11:20:25 +0000
commit3bc0eeab8f70bab8b4a1998b5d4c636a9cbfd552 (patch)
tree2c1ae41d10c0b058d2f3349c43545fd0de44e8ca /components/script
parentb925c3142407f977cd77b695b750177a9eaf940d (diff)
downloadservo-3bc0eeab8f70bab8b4a1998b5d4c636a9cbfd552.tar.gz
servo-3bc0eeab8f70bab8b4a1998b5d4c636a9cbfd552.zip
dom: Firing "click" event as synthetic pointer event (#36274)
According to specification https://html.spec.whatwg.org/multipage/webappapis.html#fire-a-click-event "Firing a click event at target means firing a synthetic pointer event named click at target" So need to replace synthetic mouse event with "click" type to pointer event. https://w3c.github.io/pointerevents/#the-click-auxclick-and-contextmenu-events https://www.w3.org/TR/uievents/#event-type-click Firing "click" event could be triggered from script or by UA: - element.click() (https://html.spec.whatwg.org/multipage/interaction.html#dom-click) - form implicit submission (https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#implicit-submission) - keyboard activation (space) --- - [x] ./mach build -d does not report any errors - [x] ./mach test-tidy does not report any errors - [x] There are tests for these changes tests/wpt/tests/shadow-dom/event-composed.html tests/wpt/tests/uievents/interface/click-event.htm Signed-off-by: Andrei Volykhin <andrei.volykhin@gmail.com>
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/document.rs35
-rw-r--r--components/script/dom/htmlelement.rs4
-rw-r--r--components/script/dom/htmlinputelement.rs2
-rw-r--r--components/script/dom/node.rs75
-rw-r--r--components/script/dom/pointerevent.rs10
5 files changed, 73 insertions, 53 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index dd521776702..78580bb20f6 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -171,7 +171,7 @@ use crate::dom::nodeiterator::NodeIterator;
use crate::dom::nodelist::NodeList;
use crate::dom::pagetransitionevent::PageTransitionEvent;
use crate::dom::performanceentry::PerformanceEntry;
-use crate::dom::pointerevent::PointerEvent;
+use crate::dom::pointerevent::{PointerEvent, PointerId};
use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::promise::Promise;
use crate::dom::range::Range;
@@ -1402,7 +1402,6 @@ impl Document {
// <https://w3c.github.io/uievents/#contextmenu>
let menu_event = PointerEvent::new(
&self.window, // window
- None, // proto
DOMString::from("contextmenu"), // type
EventBubbles::Bubbles, // can_bubble
EventCancelable::Cancelable, // cancelable
@@ -1420,22 +1419,20 @@ impl Document {
pressed_mouse_buttons, // buttons
None, // related_target
None, // point_in_target
- // TODO: decide generic pointer id
- // <https://www.w3.org/TR/pointerevents3/#dom-pointerevent-pointerid>
- 0, // pointer_id
- 1, // width
- 1, // height
- 0.5, // pressure
- 0.0, // tangential_pressure
- 0, // tilt_x
- 0, // tilt_y
- 0, // twist
- PI / 2.0, // altitude_angle
- 0.0, // azimuth_angle
- DOMString::from("mouse"), // pointer_type
- true, // is_primary
- vec![], // coalesced_events
- vec![], // predicted_events
+ PointerId::Mouse as i32, // pointer_id
+ 1, // width
+ 1, // height
+ 0.5, // pressure
+ 0.0, // tangential_pressure
+ 0, // tilt_x
+ 0, // tilt_y
+ 0, // twist
+ PI / 2.0, // altitude_angle
+ 0.0, // azimuth_angle
+ DOMString::from("mouse"), // pointer_type
+ true, // is_primary
+ vec![], // coalesced_events
+ vec![], // predicted_events
can_gc,
);
let event = menu_event.upcast::<Event>();
@@ -2186,7 +2183,7 @@ impl Document {
{
if let Some(elem) = target.downcast::<Element>() {
elem.upcast::<Node>()
- .fire_synthetic_mouse_event_not_trusted(DOMString::from("click"), can_gc);
+ .fire_synthetic_pointer_event_not_trusted(DOMString::from("click"), can_gc);
}
}
}
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs
index 5b11b3bae98..bf95f8528e9 100644
--- a/components/script/dom/htmlelement.rs
+++ b/components/script/dom/htmlelement.rs
@@ -395,7 +395,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
Some(item_attr_values.into_iter().collect())
}
- // https://html.spec.whatwg.org/multipage/#dom-click
+ /// <https://html.spec.whatwg.org/multipage/#dom-click>
fn Click(&self, can_gc: CanGc) {
let element = self.as_element();
if element.disabled_state() {
@@ -407,7 +407,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
element.set_click_in_progress(true);
self.upcast::<Node>()
- .fire_synthetic_mouse_event_not_trusted(DOMString::from("click"), can_gc);
+ .fire_synthetic_pointer_event_not_trusted(DOMString::from("click"), can_gc);
element.set_click_in_progress(false);
}
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index 901d154af17..85ebac012bb 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -2149,7 +2149,7 @@ impl HTMLInputElement {
// but we can get here from synthetic keydown events
button
.upcast::<Node>()
- .fire_synthetic_mouse_event_not_trusted(DOMString::from("click"), can_gc);
+ .fire_synthetic_pointer_event_not_trusted(DOMString::from("click"), can_gc);
}
},
None => {
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index d89263d2bf2..94e3d94b540 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -7,6 +7,7 @@
use std::borrow::Cow;
use std::cell::{Cell, LazyCell, UnsafeCell};
use std::default::Default;
+use std::f64::consts::PI;
use std::ops::Range;
use std::slice::from_ref;
use std::sync::Arc as StdArc;
@@ -105,9 +106,9 @@ use crate::dom::htmlslotelement::{HTMLSlotElement, Slottable};
use crate::dom::htmlstyleelement::HTMLStyleElement;
use crate::dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers};
use crate::dom::htmlvideoelement::{HTMLVideoElement, LayoutHTMLVideoElementHelpers};
-use crate::dom::mouseevent::MouseEvent;
use crate::dom::mutationobserver::{Mutation, MutationObserver, RegisteredObserver};
use crate::dom::nodelist::NodeList;
+use crate::dom::pointerevent::{PointerEvent, PointerId};
use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::range::WeakRangeVec;
use crate::dom::raredata::NodeRareData;
@@ -438,43 +439,59 @@ impl Node {
})
}
- /// <https://html.spec.whatg.org/#fire_a_synthetic_mouse_event>
- pub(crate) fn fire_synthetic_mouse_event_not_trusted(&self, name: DOMString, can_gc: CanGc) {
- // Spec says the choice of which global to create
- // the mouse event on is not well-defined,
+ /// <https://html.spec.whatwg.org/multipage/#fire-a-synthetic-pointer-event>
+ pub(crate) fn fire_synthetic_pointer_event_not_trusted(&self, name: DOMString, can_gc: CanGc) {
+ // Spec says the choice of which global to create the pointer event
+ // on is not well-defined,
// and refers to heycam/webidl#135
- let win = self.owner_window();
+ let window = self.owner_window();
- let mouse_event = MouseEvent::new(
- &win, // ambiguous in spec
+ // <https://w3c.github.io/pointerevents/#the-click-auxclick-and-contextmenu-events>
+ let pointer_event = PointerEvent::new(
+ &window, // ambiguous in spec
name,
- EventBubbles::Bubbles, // Step 3: bubbles
- EventCancelable::Cancelable, // Step 3: cancelable,
- Some(&win), // Step 7: view (this is unambiguous in spec)
- 0, // detail uninitialized
- 0, // coordinates uninitialized
- 0, // coordinates uninitialized
- 0, // coordinates uninitialized
- 0, // coordinates uninitialized
- false,
- false,
- false,
- false, // Step 6 modifier keys TODO compositor hook needed
- 0, // button uninitialized (and therefore left)
- 0, // buttons uninitialized (and therefore none)
- None, // related_target uninitialized,
- None, // point_in_target uninitialized,
+ EventBubbles::Bubbles, // Step 3: bubbles
+ EventCancelable::Cancelable, // Step 3: cancelable
+ Some(&window), // Step 7: view
+ 0, // detail uninitialized
+ 0, // coordinates uninitialized
+ 0, // coordinates uninitialized
+ 0, // coordinates uninitialized
+ 0, // coordinates uninitialized
+ false, // ctrl_key
+ false, // alt_key
+ false, // shift_key
+ false, // meta_key
+ 0, // button, left mouse button
+ 0, // buttons
+ None, // related_target
+ None, // point_in_target
+ PointerId::NonPointerDevice as i32, // pointer_id
+ 1, // width
+ 1, // height
+ 0.5, // pressure
+ 0.0, // tangential_pressure
+ 0, // tilt_x
+ 0, // tilt_y
+ 0, // twist
+ PI / 2.0, // altitude_angle
+ 0.0, // azimuth_angle
+ DOMString::from(""), // pointer_type
+ false, // is_primary
+ vec![], // coalesced_events
+ vec![], // predicted_events
can_gc,
);
- // Step 4: TODO composed flag for shadow root
+ // Step 4. Set event's composed flag.
+ pointer_event.upcast::<Event>().set_composed(true);
- // Step 5
- mouse_event.upcast::<Event>().set_trusted(false);
+ // Step 5. If the not trusted flag is set, initialize event's isTrusted attribute to false.
+ pointer_event.upcast::<Event>().set_trusted(false);
- // Step 8: TODO keyboard modifiers
+ // Step 6,8. TODO keyboard modifiers
- mouse_event
+ pointer_event
.upcast::<Event>()
.dispatch(self.upcast::<EventTarget>(), false, can_gc);
}
diff --git a/components/script/dom/pointerevent.rs b/components/script/dom/pointerevent.rs
index 719518c64b2..d3cd9434e7d 100644
--- a/components/script/dom/pointerevent.rs
+++ b/components/script/dom/pointerevent.rs
@@ -23,6 +23,13 @@ use crate::dom::mouseevent::MouseEvent;
use crate::dom::window::Window;
use crate::script_runtime::CanGc;
+/// <https://w3c.github.io/pointerevents/#dom-pointerevent-pointerid>
+#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
+pub(crate) enum PointerId {
+ NonPointerDevice = -1,
+ Mouse,
+}
+
#[dom_struct]
pub(crate) struct PointerEvent {
mouseevent: MouseEvent,
@@ -83,7 +90,6 @@ impl PointerEvent {
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
window: &Window,
- proto: Option<HandleObject>,
type_: DOMString,
can_bubble: EventBubbles,
cancelable: EventCancelable,
@@ -119,7 +125,7 @@ impl PointerEvent {
) -> DomRoot<PointerEvent> {
Self::new_with_proto(
window,
- proto,
+ None,
type_,
can_bubble,
cancelable,