script/dom/
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::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// 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}
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    /// <https://w3c.github.io/uievents/#initialize-a-uievent>
94    pub(crate) fn initialize_ui_event(
95        &self,
96        type_: DOMString,
97        target_: Option<&EventTarget>,
98        bubbles: EventBubbles,
99        cancelable: EventCancelable,
100    ) {
101        // 1. Initialize the base Event attributes:
102        self.event
103            .init_event(type_.into(), bool::from(bubbles), bool::from(cancelable));
104        self.event.set_target(target_);
105        // 2. Initialize view/detail:
106        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    /// <https://w3c.github.io/uievents/#dom-uievent-uievent>
124    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    // https://w3c.github.io/uievents/#widl-UIEvent-view
147    fn GetView(&self) -> Option<DomRoot<Window>> {
148        self.view.get()
149    }
150
151    // https://w3c.github.io/uievents/#widl-UIEvent-detail
152    fn Detail(&self) -> i32 {
153        self.detail.get()
154    }
155
156    // https://w3c.github.io/uievents/#widl-UIEvent-initUIEvent
157    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    // https://dom.spec.whatwg.org/#dom-event-istrusted
176    fn IsTrusted(&self) -> bool {
177        self.event.IsTrusted()
178    }
179}