1use std::cell::Cell;
6use std::default::Default;
7
8use dom_struct::dom_struct;
9use js::context::JSContext;
10use js::rust::HandleObject;
11use script_bindings::reflector::reflect_dom_object_with_proto_and_cx;
12use servo_config::pref;
13use stylo_atoms::Atom;
14
15use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods;
16use crate::dom::bindings::codegen::Bindings::UIEventBinding;
17use crate::dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
18use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods;
19use crate::dom::bindings::error::Fallible;
20use crate::dom::bindings::inheritance::Castable;
21use crate::dom::bindings::root::{DomRoot, MutNullableDom};
22use crate::dom::bindings::str::DOMString;
23use crate::dom::element::Element;
24use crate::dom::event::{Event, EventBubbles, EventCancelable};
25use crate::dom::eventtarget::EventTarget;
26use crate::dom::node::NodeTraits;
27use crate::dom::window::Window;
28
29#[dom_struct]
31pub(crate) struct UIEvent {
32 event: Event,
33 view: MutNullableDom<Window>,
34 detail: Cell<i32>,
35 which: Cell<u32>,
36}
37
38impl UIEvent {
39 pub(crate) fn new_inherited() -> UIEvent {
40 UIEvent {
41 event: Event::new_inherited(),
42 view: Default::default(),
43 detail: Cell::new(0),
44 which: Cell::new(0),
45 }
46 }
47
48 pub(crate) fn set_which(&self, v: u32) {
49 self.which.set(v);
50 }
51
52 pub(crate) fn new_uninitialized(cx: &mut JSContext, window: &Window) -> DomRoot<UIEvent> {
53 Self::new_uninitialized_with_proto(cx, window, None)
54 }
55
56 fn new_uninitialized_with_proto(
57 cx: &mut JSContext,
58 window: &Window,
59 proto: Option<HandleObject>,
60 ) -> DomRoot<UIEvent> {
61 reflect_dom_object_with_proto_and_cx(Box::new(UIEvent::new_inherited()), window, proto, cx)
62 }
63
64 #[allow(clippy::too_many_arguments)]
65 pub(crate) fn new(
66 cx: &mut JSContext,
67 window: &Window,
68 event_type: Atom,
69 can_bubble: EventBubbles,
70 cancelable: EventCancelable,
71 view: Option<&Window>,
72 detail: i32,
73 which: u32,
74 ) -> DomRoot<UIEvent> {
75 Self::new_with_proto(
76 cx, window, None, event_type, can_bubble, cancelable, view, detail, which,
77 )
78 }
79
80 #[allow(clippy::too_many_arguments)]
81 fn new_with_proto(
82 cx: &mut JSContext,
83 window: &Window,
84 proto: Option<HandleObject>,
85 event_type: Atom,
86 can_bubble: EventBubbles,
87 cancelable: EventCancelable,
88 view: Option<&Window>,
89 detail: i32,
90 which: u32,
91 ) -> DomRoot<UIEvent> {
92 let ev = UIEvent::new_uninitialized_with_proto(cx, window, proto);
93 ev.initialize_ui_event(
94 event_type,
95 view.map(|window| window.upcast::<EventTarget>()),
96 can_bubble,
97 cancelable,
98 );
99 ev.detail.set(detail);
100 ev.which.set(which);
101 ev
102 }
103
104 pub(crate) fn initialize_ui_event(
106 &self,
107 event_type: Atom,
108 target_: Option<&EventTarget>,
109 bubbles: EventBubbles,
110 cancelable: EventCancelable,
111 ) {
112 self.event
114 .init_event(event_type, bool::from(bubbles), bool::from(cancelable));
115 self.event.set_target(target_);
116 if let Some(target_) = target_ {
118 let element = target_.downcast::<Element>();
119 let document = match element {
120 Some(element) => element.owner_document(),
121 None => target_.downcast::<Window>().unwrap().Document(),
122 };
123 self.view.set(Some(document.window()));
124 }
125 self.detail.set(0_i32);
126 }
127
128 pub(crate) fn set_detail(&self, detail_: i32) {
129 self.detail.set(detail_);
130 }
131
132 pub(crate) fn init_event(
134 &self,
135 event_type: Atom,
136 can_bubble: bool,
137 cancelable: bool,
138 view: Option<&Window>,
139 detail: i32,
140 ) {
141 let event = self.upcast::<Event>();
142 if event.dispatching() {
143 return;
144 }
145
146 event.init_event(event_type, can_bubble, cancelable);
147 self.view.set(view);
148 self.detail.set(detail);
149 }
150}
151
152impl UIEventMethods<crate::DomTypeHolder> for UIEvent {
153 fn Constructor(
155 cx: &mut JSContext,
156 window: &Window,
157 proto: Option<HandleObject>,
158 event_type: DOMString,
159 init: &UIEventBinding::UIEventInit,
160 ) -> Fallible<DomRoot<UIEvent>> {
161 let bubbles = EventBubbles::from(init.parent.bubbles);
162 let cancelable = EventCancelable::from(init.parent.cancelable);
163 let event = UIEvent::new_with_proto(
164 cx,
165 window,
166 proto,
167 event_type.into(),
168 bubbles,
169 cancelable,
170 init.view.as_deref(),
171 init.detail,
172 init.which,
173 );
174 Ok(event)
175 }
176
177 fn GetView(&self) -> Option<DomRoot<Window>> {
179 self.view.get()
180 }
181
182 fn Detail(&self) -> i32 {
184 self.detail.get()
185 }
186
187 fn InitUIEvent(
189 &self,
190 event_type: DOMString,
191 can_bubble: bool,
192 cancelable: bool,
193 view: Option<&Window>,
194 detail: i32,
195 ) {
196 self.init_event(event_type.into(), can_bubble, cancelable, view, detail);
197 }
198
199 fn IsTrusted(&self) -> bool {
201 self.event.IsTrusted()
202 }
203
204 fn Which(&self) -> u32 {
206 if pref!(dom_uievent_which_enabled) {
207 self.which.get()
208 } else {
209 0
210 }
211 }
212}