1use std::cell::Cell;
6use std::default::Default;
7
8use dom_struct::dom_struct;
9use js::rust::HandleObject;
10use servo_config::pref;
11use stylo_atoms::Atom;
12
13use super::node::NodeTraits;
14use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods;
15use crate::dom::bindings::codegen::Bindings::UIEventBinding;
16use crate::dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
17use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods;
18use crate::dom::bindings::error::Fallible;
19use crate::dom::bindings::inheritance::Castable;
20use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
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::window::Window;
27use crate::script_runtime::CanGc;
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(window: &Window, can_gc: CanGc) -> DomRoot<UIEvent> {
53 Self::new_uninitialized_with_proto(window, None, can_gc)
54 }
55
56 fn new_uninitialized_with_proto(
57 window: &Window,
58 proto: Option<HandleObject>,
59 can_gc: CanGc,
60 ) -> DomRoot<UIEvent> {
61 reflect_dom_object_with_proto(Box::new(UIEvent::new_inherited()), window, proto, can_gc)
62 }
63
64 #[allow(clippy::too_many_arguments)]
65 pub(crate) fn new(
66 window: &Window,
67 type_: DOMString,
68 can_bubble: EventBubbles,
69 cancelable: EventCancelable,
70 view: Option<&Window>,
71 detail: i32,
72 which: u32,
73 can_gc: CanGc,
74 ) -> DomRoot<UIEvent> {
75 Self::new_with_proto(
76 window, None, type_, can_bubble, cancelable, view, detail, which, can_gc,
77 )
78 }
79
80 #[allow(clippy::too_many_arguments)]
81 fn new_with_proto(
82 window: &Window,
83 proto: Option<HandleObject>,
84 type_: DOMString,
85 can_bubble: EventBubbles,
86 cancelable: EventCancelable,
87 view: Option<&Window>,
88 detail: i32,
89 which: u32,
90 can_gc: CanGc,
91 ) -> DomRoot<UIEvent> {
92 let ev = UIEvent::new_uninitialized_with_proto(window, proto, can_gc);
93 ev.initialize_ui_event(
94 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 type_: DOMString,
108 target_: Option<&EventTarget>,
109 bubbles: EventBubbles,
110 cancelable: EventCancelable,
111 ) {
112 self.event
114 .init_event(type_.into(), 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
133impl UIEventMethods<crate::DomTypeHolder> for UIEvent {
134 fn Constructor(
136 window: &Window,
137 proto: Option<HandleObject>,
138 can_gc: CanGc,
139 type_: DOMString,
140 init: &UIEventBinding::UIEventInit,
141 ) -> Fallible<DomRoot<UIEvent>> {
142 let bubbles = EventBubbles::from(init.parent.bubbles);
143 let cancelable = EventCancelable::from(init.parent.cancelable);
144 let event = UIEvent::new_with_proto(
145 window,
146 proto,
147 type_,
148 bubbles,
149 cancelable,
150 init.view.as_deref(),
151 init.detail,
152 init.which,
153 can_gc,
154 );
155 Ok(event)
156 }
157
158 fn GetView(&self) -> Option<DomRoot<Window>> {
160 self.view.get()
161 }
162
163 fn Detail(&self) -> i32 {
165 self.detail.get()
166 }
167
168 fn InitUIEvent(
170 &self,
171 type_: DOMString,
172 can_bubble: bool,
173 cancelable: bool,
174 view: Option<&Window>,
175 detail: i32,
176 ) {
177 let event = self.upcast::<Event>();
178 if event.dispatching() {
179 return;
180 }
181
182 event.init_event(Atom::from(type_), can_bubble, cancelable);
183 self.view.set(view);
184 self.detail.set(detail);
185 }
186
187 fn IsTrusted(&self) -> bool {
189 self.event.IsTrusted()
190 }
191
192 fn Which(&self) -> u32 {
194 if pref!(dom_uievent_which_enabled) {
195 self.which.get()
196 } else {
197 0
198 }
199 }
200}