1use std::cell::Cell;
6use std::default::Default;
7
8use dom_struct::dom_struct;
9use js::rust::HandleObject;
10use stylo_atoms::Atom;
11
12use super::node::NodeTraits;
13use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods;
14use crate::dom::bindings::codegen::Bindings::UIEventBinding;
15use crate::dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
16use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods;
17use crate::dom::bindings::error::Fallible;
18use crate::dom::bindings::inheritance::Castable;
19use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
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::window::Window;
26use crate::script_runtime::CanGc;
27
28#[dom_struct]
30pub(crate) struct UIEvent {
31 event: Event,
32 view: MutNullableDom<Window>,
33 detail: Cell<i32>,
34}
35
36impl UIEvent {
37 pub(crate) fn new_inherited() -> UIEvent {
38 UIEvent {
39 event: Event::new_inherited(),
40 view: Default::default(),
41 detail: Cell::new(0),
42 }
43 }
44
45 pub(crate) fn new_uninitialized(window: &Window, can_gc: CanGc) -> DomRoot<UIEvent> {
46 Self::new_uninitialized_with_proto(window, None, can_gc)
47 }
48
49 fn new_uninitialized_with_proto(
50 window: &Window,
51 proto: Option<HandleObject>,
52 can_gc: CanGc,
53 ) -> DomRoot<UIEvent> {
54 reflect_dom_object_with_proto(Box::new(UIEvent::new_inherited()), window, proto, can_gc)
55 }
56
57 pub(crate) fn new(
58 window: &Window,
59 type_: DOMString,
60 can_bubble: EventBubbles,
61 cancelable: EventCancelable,
62 view: Option<&Window>,
63 detail: i32,
64 can_gc: CanGc,
65 ) -> DomRoot<UIEvent> {
66 Self::new_with_proto(
67 window, None, type_, can_bubble, cancelable, view, detail, can_gc,
68 )
69 }
70
71 #[allow(clippy::too_many_arguments)]
72 fn new_with_proto(
73 window: &Window,
74 proto: Option<HandleObject>,
75 type_: DOMString,
76 can_bubble: EventBubbles,
77 cancelable: EventCancelable,
78 view: Option<&Window>,
79 detail: i32,
80 can_gc: CanGc,
81 ) -> DomRoot<UIEvent> {
82 let ev = UIEvent::new_uninitialized_with_proto(window, proto, can_gc);
83 ev.initialize_ui_event(
84 type_,
85 view.map(|window| window.upcast::<EventTarget>()),
86 can_bubble,
87 cancelable,
88 );
89 ev.detail.set(detail);
90 ev
91 }
92
93 pub(crate) fn initialize_ui_event(
95 &self,
96 type_: DOMString,
97 target_: Option<&EventTarget>,
98 bubbles: EventBubbles,
99 cancelable: EventCancelable,
100 ) {
101 self.event
103 .init_event(type_.into(), bool::from(bubbles), bool::from(cancelable));
104 self.event.set_target(target_);
105 if let Some(target_) = target_ {
107 let element = target_.downcast::<Element>();
108 let document = match element {
109 Some(element) => element.owner_document(),
110 None => target_.downcast::<Window>().unwrap().Document(),
111 };
112 self.view.set(Some(document.window()));
113 }
114 self.detail.set(0_i32);
115 }
116
117 pub(crate) fn set_detail(&self, detail_: i32) {
118 self.detail.set(detail_);
119 }
120}
121
122impl UIEventMethods<crate::DomTypeHolder> for UIEvent {
123 fn Constructor(
125 window: &Window,
126 proto: Option<HandleObject>,
127 can_gc: CanGc,
128 type_: DOMString,
129 init: &UIEventBinding::UIEventInit,
130 ) -> Fallible<DomRoot<UIEvent>> {
131 let bubbles = EventBubbles::from(init.parent.bubbles);
132 let cancelable = EventCancelable::from(init.parent.cancelable);
133 let event = UIEvent::new_with_proto(
134 window,
135 proto,
136 type_,
137 bubbles,
138 cancelable,
139 init.view.as_deref(),
140 init.detail,
141 can_gc,
142 );
143 Ok(event)
144 }
145
146 fn GetView(&self) -> Option<DomRoot<Window>> {
148 self.view.get()
149 }
150
151 fn Detail(&self) -> i32 {
153 self.detail.get()
154 }
155
156 fn InitUIEvent(
158 &self,
159 type_: DOMString,
160 can_bubble: bool,
161 cancelable: bool,
162 view: Option<&Window>,
163 detail: i32,
164 ) {
165 let event = self.upcast::<Event>();
166 if event.dispatching() {
167 return;
168 }
169
170 event.init_event(Atom::from(type_), can_bubble, cancelable);
171 self.view.set(view);
172 self.detail.set(detail);
173 }
174
175 fn IsTrusted(&self) -> bool {
177 self.event.IsTrusted()
178 }
179}