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