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 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// https://w3c.github.io/uievents/#interface-uievent
30#[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    /// <https://w3c.github.io/uievents/#initialize-a-uievent>
105    pub(crate) fn initialize_ui_event(
106        &self,
107        type_: DOMString,
108        target_: Option<&EventTarget>,
109        bubbles: EventBubbles,
110        cancelable: EventCancelable,
111    ) {
112        // 1. Initialize the base Event attributes:
113        self.event
114            .init_event(type_.into(), bool::from(bubbles), bool::from(cancelable));
115        self.event.set_target(target_);
116        // 2. Initialize view/detail:
117        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    /// <https://w3c.github.io/uievents/#dom-uievent-uievent>
135    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    /// <https://w3c.github.io/uievents/#widl-UIEvent-view>
159    fn GetView(&self) -> Option<DomRoot<Window>> {
160        self.view.get()
161    }
162
163    /// <https://w3c.github.io/uievents/#widl-UIEvent-detail>
164    fn Detail(&self) -> i32 {
165        self.detail.get()
166    }
167
168    /// <https://w3c.github.io/uievents/#widl-UIEvent-initUIEvent>
169    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    /// <https://dom.spec.whatwg.org/#dom-event-istrusted>
188    fn IsTrusted(&self) -> bool {
189        self.event.IsTrusted()
190    }
191
192    /// <https://w3c.github.io/uievents/#dom-uievent-which>
193    fn Which(&self) -> u32 {
194        if pref!(dom_uievent_which_enabled) {
195            self.which.get()
196        } else {
197            0
198        }
199    }
200}