Skip to main content

script/dom/event/
uievent.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use 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// https://w3c.github.io/uievents/#interface-uievent
29#[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    /// <https://w3c.github.io/uievents/#initialize-a-uievent>
104    pub(crate) fn initialize_ui_event(
105        &self,
106        event_type: Atom,
107        target_: Option<&EventTarget>,
108        bubbles: EventBubbles,
109        cancelable: EventCancelable,
110    ) {
111        // 1. Initialize the base Event attributes:
112        self.event
113            .init_event(event_type, bool::from(bubbles), bool::from(cancelable));
114        self.event.set_target(target_);
115        // 2. Initialize view/detail:
116        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    /// <https://w3c.github.io/uievents/#widl-UIEvent-initUIEvent>
132    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    /// <https://w3c.github.io/uievents/#dom-uievent-uievent>
153    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    /// <https://w3c.github.io/uievents/#widl-UIEvent-view>
177    fn GetView(&self) -> Option<DomRoot<Window>> {
178        self.view.get()
179    }
180
181    /// <https://w3c.github.io/uievents/#widl-UIEvent-detail>
182    fn Detail(&self) -> i32 {
183        self.detail.get()
184    }
185
186    /// <https://w3c.github.io/uievents/#widl-UIEvent-initUIEvent>
187    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    /// <https://dom.spec.whatwg.org/#dom-event-istrusted>
199    fn IsTrusted(&self) -> bool {
200        self.event.IsTrusted()
201    }
202
203    /// <https://w3c.github.io/uievents/#dom-uievent-which>
204    fn Which(&self) -> u32 {
205        self.which.get()
206    }
207}