script/dom/event/
inputevent.rs1use bitflags::bitflags;
6use dom_struct::dom_struct;
7use embedder_traits::Cursor;
8use euclid::Point2D;
9use js::context::JSContext;
10use js::rust::HandleObject;
11use script_bindings::domstring::TracedDOMString;
12use script_bindings::reflector::reflect_dom_object_with_proto;
13use style::Atom;
14use style_traits::CSSPixel;
15
16use crate::dom::bindings::codegen::Bindings::InputEventBinding::{self, InputEventMethods};
17use crate::dom::bindings::codegen::Bindings::UIEventBinding::UIEvent_Binding::UIEventMethods;
18use crate::dom::bindings::error::Fallible;
19use crate::dom::bindings::root::DomRoot;
20use crate::dom::bindings::str::DOMString;
21use crate::dom::datatransfer::DataTransfer;
22use crate::dom::node::Node;
23use crate::dom::selection_range::RootedSelectionBoundary;
24use crate::dom::staticrange::StaticRange;
25use crate::dom::uievent::UIEvent;
26use crate::dom::window::Window;
27
28#[dom_struct]
29pub(crate) struct InputEvent {
30 uievent: UIEvent,
31 data: Option<TracedDOMString>,
32 is_composing: bool,
33 input_type: TracedDOMString,
34}
35
36impl InputEvent {
37 #[expect(clippy::too_many_arguments)]
38 pub(crate) fn new(
39 cx: &mut JSContext,
40 window: &Window,
41 proto: Option<HandleObject>,
42 event_type: Atom,
43 flags: InputEventFlags,
44 view: Option<&Window>,
45 detail: i32,
46 data: Option<DOMString>,
47 input_type: DOMString,
48 ) -> DomRoot<InputEvent> {
49 let event = reflect_dom_object_with_proto(
50 cx,
51 Box::new(InputEvent {
52 uievent: UIEvent::new_inherited(),
53 data: data.map(|domstring| domstring.traced()),
54 is_composing: flags.intersects(InputEventFlags::COMPOSING),
55 input_type: input_type.traced(),
56 }),
57 window,
58 proto,
59 );
60 event.uievent.init_event(
61 event_type,
62 flags.intersects(InputEventFlags::BUBBLES),
63 flags.intersects(InputEventFlags::CANCELABLE),
64 view,
65 detail,
66 );
67 event
68 }
69}
70
71impl InputEventMethods<crate::DomTypeHolder> for InputEvent {
72 fn Constructor(
74 cx: &mut JSContext,
75 window: &Window,
76 proto: Option<HandleObject>,
77 event_type: DOMString,
78 init: &InputEventBinding::InputEventInit,
79 ) -> Fallible<DomRoot<InputEvent>> {
80 let mut flags = InputEventFlags::empty();
81 if init.parent.parent.bubbles {
82 flags |= InputEventFlags::BUBBLES;
83 }
84 if init.parent.parent.cancelable {
85 flags |= InputEventFlags::CANCELABLE;
86 }
87 if init.isComposing {
88 flags |= InputEventFlags::COMPOSING;
89 }
90 let event = InputEvent::new(
91 cx,
92 window,
93 proto,
94 event_type.into(),
95 flags,
96 init.parent.view.as_deref(),
97 init.parent.detail,
98 init.data.clone(),
99 init.inputType.clone(),
100 );
101 Ok(event)
102 }
103
104 fn GetData(&self) -> Option<DOMString> {
106 self.data.clone().map(|domstring| domstring.root())
107 }
108
109 fn IsComposing(&self) -> bool {
111 self.is_composing
112 }
113
114 fn InputType(&self) -> DOMString {
116 self.input_type.clone().root()
117 }
118
119 fn GetDataTransfer(&self) -> Option<DomRoot<DataTransfer>> {
121 None
123 }
124
125 fn GetTargetRanges(&self) -> Vec<DomRoot<StaticRange>> {
127 Vec::new()
129 }
130
131 fn IsTrusted(&self) -> bool {
133 self.uievent.IsTrusted()
134 }
135}
136
137bitflags! {
138 #[derive(Clone, Copy, Eq, PartialEq)]
139 pub struct InputEventFlags: u8 {
140 const BUBBLES = 1 << 0;
141 const CANCELABLE = 1 << 1;
142 const COMPOSING = 1 << 2;
143 }
144}
145pub(crate) struct HitTestResult {
148 pub node: DomRoot<Node>,
149 pub dom_position_for_selection: Option<RootedSelectionBoundary>,
150 pub cursor: Cursor,
151 pub point_in_node: Point2D<f32, CSSPixel>,
152 pub point_in_frame: Point2D<f32, CSSPixel>,
153 pub point_relative_to_initial_containing_block: Point2D<f32, CSSPixel>,
154}