stdweb/webapi/events/
pointer.rs

1use webcore::value::Reference;
2use webcore::try_from::TryInto;
3use webapi::event::{IEvent, IUiEvent, UiEvent, Event};
4use webapi::events::mouse::{IMouseEvent, MouseEvent};
5
6#[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")]
7use webapi::events::mouse::MouseButton;
8
9/// The `IPointerEvent` interface represents the state of a DOM event produced by a pointer
10/// such as the geometry of the contact point, the device type that generated the event, the
11/// amount of pressure that was applied on the contact surface, etc.
12///
13/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent)
14// https://w3c.github.io/pointerevents/#pointerevent-interface
15// https://w3c.github.io/pointerevents/extension.html#extensions-to-the-pointerevent-interface
16pub trait IPointerEvent: IMouseEvent {
17    /// Returns a unique identifier for the pointer causing the event.
18    ///
19    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerId)
20    // https://w3c.github.io/pointerevents/#dom-pointerevent-pointerid
21    #[inline]
22    fn pointer_id( &self ) -> i32 {
23        js!(
24            return @{self.as_ref()}.pointerId;
25        ).try_into().unwrap()
26    }
27
28    /// Returns the width, in CSS pixels, of the contact geometry of the pointer.
29    ///
30    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/width)
31    // https://w3c.github.io/pointerevents/#dom-pointerevent-width
32    #[inline]
33    fn width( &self ) -> f64 {
34        js!(
35            return @{self.as_ref()}.width;
36        ).try_into().unwrap()
37    }
38
39    /// Returns the height, in CSS pixels, of the contact geometry of the pointer.
40    ///
41    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/height)
42    // https://w3c.github.io/pointerevents/#dom-pointerevent-height
43    #[inline]
44    fn height( &self ) -> f64 {
45        js!(
46            return @{self.as_ref()}.height;
47        ).try_into().unwrap()
48    }
49
50    /// Returns the normalized pressure of the pointer in the range [0, 1]
51    ///
52    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pressure)
53    // https://w3c.github.io/pointerevents/#dom-pointerevent-pressure
54    //TODO: This should return a f32, but try_into() didn't support it at the time of writing
55    #[inline]
56    fn pressure( &self ) -> f64 {
57        js!(
58            return @{self.as_ref()}.pressure;
59        ).try_into().unwrap()
60    }
61
62    /// Returns the normalized tangential pressure of the pointer in the range [-1, 1], where 0 is
63    /// the hardware's neutral position
64    ///
65    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tangentialPressure)
66    // https://w3c.github.io/pointerevents/#dom-pointerevent-tangentialpressure
67    //TODO: This should return a f32, but try_into() didn't support it at the time of writing
68    #[inline]
69    fn tangential_pressure( &self ) -> f64 {
70        js!(
71            return @{self.as_ref()}.tangentialPressure;
72        ).try_into().unwrap()
73    }
74
75    /// Returns the angle, in the range of [-90, 90] degrees, between the Y-Z plane and the plane
76    /// containing the transducer (e.g. pen stylus) and the Y axis.
77    ///
78    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tiltX)
79    // https://w3c.github.io/pointerevents/#dom-pointerevent-tiltx
80    #[inline]
81    fn tilt_x( &self ) -> i32 {
82        js!(
83            return @{self.as_ref()}.tiltX;
84        ).try_into().unwrap()
85    }
86
87    /// Returns the angle, in the range of [-90, 90] degrees, between the X-Z plane and the plane
88    /// containing the transducer (e.g. pen stylus) and the X axis.
89    ///
90    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tiltY)
91    // https://w3c.github.io/pointerevents/#dom-pointerevent-tilty
92    #[inline]
93    fn tilt_y( &self ) -> i32 {
94        js!(
95            return @{self.as_ref()}.tiltY;
96        ).try_into().unwrap()
97    }
98
99    /// Returns the clockwise rotation, in the range of [0, 359] degrees, of
100    /// the transducer (e.g. pen stylus) around it's own major axis
101    ///
102    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/twist)
103    // https://w3c.github.io/pointerevents/#dom-pointerevent-twist
104    #[inline]
105    fn twist( &self ) -> i32 {
106        js!(
107            return @{self.as_ref()}.twist;
108        ).try_into().unwrap()
109    }
110
111    /// Indicates the device type that caused the event.
112    ///
113    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerType)
114    // https://w3c.github.io/pointerevents/#dom-pointerevent-pointertype
115    #[inline]
116    fn pointer_type( &self ) -> String {
117        js!(
118            return @{self.as_ref()}.pointerType;
119        ).try_into().unwrap()
120    }
121
122    /// Indicates if the pointer represents the primary pointer of this pointer type
123    ///
124    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/isPrimary)
125    // https://w3c.github.io/pointerevents/#dom-pointerevent-isprimary
126    #[inline]
127    fn is_primary( &self ) -> bool {
128        js!(
129            return @{self.as_ref()}.isPrimary;
130        ).try_into().unwrap()
131    }
132
133    /// Indicates the mouse button that fired this event. A None value indicates no change since the last PointerEvent.
134    ///
135    /// This function is feature-gated because it may be merged into `MouseEvent::button()`
136    ///
137    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button)
138    // https://w3c.github.io/pointerevents/#the-button-property
139    #[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")]
140    fn button_pointer( &self ) -> Option<MouseButton> {
141        match js!(
142            return @{self.as_ref()}.button;
143        ).try_into().unwrap() {
144            -1 => None,
145            0 => Some(MouseButton::Left),
146            1 => Some(MouseButton::Wheel),
147            2 => Some(MouseButton::Right),
148            3 => Some(MouseButton::Button4),
149            4 => Some(MouseButton::Button5),
150            _ => unreachable!("Unexpected PointerEvent.button value"),
151        }
152    }
153}
154
155/// A reference to a JavaScript object which implements the [IPointerEvent](trait.IPointerEvent.html)
156/// interface.
157///
158/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent)
159// https://w3c.github.io/pointerevents/#pointerevent-interface
160#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
161#[reference(instance_of = "PointerEvent")]
162#[reference(subclass_of(Event, UiEvent, MouseEvent))]
163pub struct PointerEvent( Reference );
164
165impl IEvent for PointerEvent {}
166impl IUiEvent for PointerEvent {}
167impl IMouseEvent for PointerEvent {}
168impl IPointerEvent for PointerEvent {}
169
170/// The `PointerOverEvent` is fired when a pointing device is moved into
171/// a element's hit test boundaries.
172///
173/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerover)
174// https://w3c.github.io/pointerevents/#the-pointerover-event
175#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
176#[reference(instance_of = "PointerEvent")]
177#[reference(event = "pointerover")]
178#[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))]
179pub struct PointerOverEvent( Reference );
180
181impl IEvent for PointerOverEvent {}
182impl IUiEvent for PointerOverEvent {}
183impl IMouseEvent for PointerOverEvent {}
184impl IPointerEvent for PointerOverEvent {}
185
186/// The `PointerEnterEvent` is fired when a pointing device is moved into
187/// the hit test boundaries of an element or its descendants. This event does not bubble.
188///
189/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerenter)
190// https://w3c.github.io/pointerevents/#the-pointerenter-event
191#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
192#[reference(instance_of = "PointerEvent")]
193#[reference(event = "pointerenter")]
194#[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))]
195pub struct PointerEnterEvent( Reference );
196
197impl IEvent for PointerEnterEvent {}
198impl IUiEvent for PointerEnterEvent {}
199impl IMouseEvent for PointerEnterEvent {}
200impl IPointerEvent for PointerEnterEvent {}
201
202/// The `PointerDownEvent` is fired when a pointer becomes active
203///
204/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerdown)
205// https://w3c.github.io/pointerevents/#the-pointerdown-event
206#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
207#[reference(instance_of = "PointerEvent")]
208#[reference(event = "pointerdown")]
209#[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))]
210pub struct PointerDownEvent( Reference );
211
212impl IEvent for PointerDownEvent {}
213impl IUiEvent for PointerDownEvent {}
214impl IMouseEvent for PointerDownEvent {}
215impl IPointerEvent for PointerDownEvent {}
216
217/// The `PointerMoveEvent` is fired when a pointer changes coordinates
218///
219/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointermove)
220// https://w3c.github.io/pointerevents/#the-pointermove-event
221#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
222#[reference(instance_of = "PointerEvent")]
223#[reference(event = "pointermove")]
224#[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))]
225pub struct PointerMoveEvent( Reference );
226
227impl IEvent for PointerMoveEvent {}
228impl IUiEvent for PointerMoveEvent {}
229impl IMouseEvent for PointerMoveEvent {}
230impl IPointerEvent for PointerMoveEvent {}
231
232impl PointerMoveEvent
233{
234    /// Returns the sequence of all `PointerEvent` instances that were coalesced into the dispatched `PointerMoveEvent`.
235    ///
236    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/getCoalescedEvents)
237    // https://w3c.github.io/pointerevents/extension.html#dom-pointerevent-getcoalescedevents
238    #[inline]
239    pub fn get_coalesced_events( &self ) -> Vec<PointerEvent> {
240        js!(
241            return @{self.as_ref()}.getCoalescedEvents();
242        ).try_into().unwrap()
243    }
244}
245
246/// The `PointerUpEvent` is fired when a pointer is no longer active
247///
248/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerup)
249// https://w3c.github.io/pointerevents/#the-pointerup-event
250#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
251#[reference(instance_of = "PointerEvent")]
252#[reference(event = "pointerup")]
253#[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))]
254pub struct PointerUpEvent( Reference );
255
256impl IEvent for PointerUpEvent {}
257impl IUiEvent for PointerUpEvent {}
258impl IMouseEvent for PointerUpEvent {}
259impl IPointerEvent for PointerUpEvent {}
260
261/// The `PointerCancelEvent` is fired when a pointer will no longer produce events
262/// (for example the device is deactivated), or if the pointer starts a gesture after a pointerdown event
263/// (for example panning, zooming, or drag and drop)
264///
265/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointercancel)
266// https://w3c.github.io/pointerevents/#the-pointercancel-event
267#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
268#[reference(instance_of = "PointerEvent")]
269#[reference(event = "pointercancel")]
270#[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))]
271pub struct PointerCancelEvent( Reference );
272
273impl IEvent for PointerCancelEvent {}
274impl IUiEvent for PointerCancelEvent {}
275impl IMouseEvent for PointerCancelEvent {}
276impl IPointerEvent for PointerCancelEvent {}
277
278/// The `PointerOutEvent` is fired when the pointer moves out of the hit test boundaries of an element.
279/// This can include when a finger leaves a touch screen or a pen leaves the detectable hover range.
280///
281/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerout)
282// https://w3c.github.io/pointerevents/#the-pointerout-event
283#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
284#[reference(instance_of = "PointerEvent")]
285#[reference(event = "pointerout")]
286#[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))]
287pub struct PointerOutEvent( Reference );
288
289impl IEvent for PointerOutEvent {}
290impl IUiEvent for PointerOutEvent {}
291impl IMouseEvent for PointerOutEvent {}
292impl IPointerEvent for PointerOutEvent {}
293
294/// The `PointerLeaveEvent` is fired when the pointer moves out of the hit test boundaries
295/// of an element and it's descendants. This can include when a finger leaves a touch screen
296/// or a pen leaves the detectable hover range. This event does not bubble.
297///
298/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerleave)
299// https://w3c.github.io/pointerevents/#the-pointerleave-event
300#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
301#[reference(instance_of = "PointerEvent")]
302#[reference(event = "pointerleave")]
303#[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))]
304pub struct PointerLeaveEvent( Reference );
305
306impl IEvent for PointerLeaveEvent {}
307impl IUiEvent for PointerLeaveEvent {}
308impl IMouseEvent for PointerLeaveEvent {}
309impl IPointerEvent for PointerLeaveEvent {}
310
311/// The `GotPointerCaptureEvent` fires when an element receives pointer capture
312///
313/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/gotpointercapture)
314// https://w3c.github.io/pointerevents/#the-gotpointercapture-event
315#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
316#[reference(instance_of = "PointerEvent")]
317#[reference(event = "gotpointercapture")]
318#[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))]
319pub struct GotPointerCaptureEvent( Reference );
320
321impl IEvent for GotPointerCaptureEvent {}
322impl IUiEvent for GotPointerCaptureEvent {}
323impl IMouseEvent for GotPointerCaptureEvent {}
324impl IPointerEvent for GotPointerCaptureEvent {}
325
326/// The `LostPointerCaptureEvent` fires when an element loses pointer capture
327///
328/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/lostpointercapture)
329// https://w3c.github.io/pointerevents/#the-lostpointercapture-event
330#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
331#[reference(instance_of = "PointerEvent")]
332#[reference(event = "lostpointercapture")]
333#[reference(subclass_of(Event, UiEvent, MouseEvent, PointerEvent))]
334pub struct LostPointerCaptureEvent( Reference );
335
336impl IEvent for LostPointerCaptureEvent {}
337impl IUiEvent for LostPointerCaptureEvent {}
338impl IMouseEvent for LostPointerCaptureEvent {}
339impl IPointerEvent for LostPointerCaptureEvent {}
340
341/// The `PointerLockChangeEvent` fires when the pointer is locked or unlocked
342///
343/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerlockchange)
344// http://www.w3.org/TR/pointerlock/#pointerlockchange-and-pointerlockerror-events
345#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
346#[reference(instance_of = "Event")]
347#[reference(event = "pointerlockchange")]
348#[reference(subclass_of(Event))]
349pub struct PointerLockChangeEvent( Reference );
350
351impl IEvent for PointerLockChangeEvent {}
352
353/// The `PointerLockErrorEvent` fires when an error occurs locking a pointer
354///
355/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/pointerlockerror)
356// http://www.w3.org/TR/pointerlock/#pointerlockchange-and-pointerlockerror-events
357#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
358#[reference(instance_of = "Event")]
359#[reference(event = "pointerlockerror")]
360#[reference(subclass_of(Event))]
361pub struct PointerLockErrorEvent( Reference );
362
363impl IEvent for PointerLockErrorEvent {}
364
365#[cfg(all(test, feature = "web_test"))]
366mod tests {
367    use super::*;
368    use webapi::event::ConcreteEvent;
369
370    #[test]
371    fn test_pointer_event() {
372        let event: PointerMoveEvent = js!(
373            return new PointerEvent(
374                @{PointerMoveEvent::EVENT_TYPE},
375                {
376                    altKey: false,
377                    button: -1,
378                    buttons: 6,
379                    clientX: 3,
380                    clientY: 4,
381                    ctrlKey: true,
382                    metaKey: false,
383                    screenX: 1,
384                    screenY: 2,
385                    shiftKey: true,
386
387                    pointerId: 5,
388                    width: 8.2,
389                    height: 6.1,
390                    pressure: 0.49,
391                    tangentialPressure: -0.2,
392                    tiltX: 20,
393                    tiltY: -42,
394                    twist: 215,
395                    pointerType: "stdweb-hand-wave",
396                    isPrimary: false,
397                }
398            );
399        ).try_into().unwrap();
400
401        assert_eq!( event.event_type(), PointerMoveEvent::EVENT_TYPE );
402
403        assert_eq!( event.pointer_id(), 5 );
404        assert_eq!( event.width(), 8.2 );
405        assert_eq!( event.height(), 6.1 );
406        assert!( ( event.pressure() - 0.49 ).abs() < 0.00000001 );
407        assert!( ( event.tangential_pressure() - -0.2 ).abs() < 0.00000001 );
408        assert_eq!( event.tilt_x(), 20 );
409        assert_eq!( event.tilt_y(), -42 );
410        assert_eq!( event.twist(), 215 );
411        assert_eq!( event.pointer_type(), "stdweb-hand-wave" );
412        assert_eq!( event.is_primary(), false );
413
414        assert_eq!( event.get_coalesced_events().len(), 0 );
415    }
416
417    #[test]
418    fn test_pointer_over_event() {
419        let event: PointerOverEvent = js!(
420            return new PointerEvent( @{PointerOverEvent::EVENT_TYPE} );
421        ).try_into().unwrap();
422        assert_eq!( event.event_type(), PointerOverEvent::EVENT_TYPE );
423    }
424
425    #[test]
426    fn test_pointer_enter_event() {
427        let event: PointerEnterEvent = js!(
428            return new PointerEvent( @{PointerEnterEvent::EVENT_TYPE} );
429        ).try_into().unwrap();
430        assert_eq!( event.event_type(), PointerEnterEvent::EVENT_TYPE );
431    }
432
433    #[test]
434    fn test_pointer_down_event() {
435        let event: PointerDownEvent = js!(
436            return new PointerEvent( @{PointerDownEvent::EVENT_TYPE} );
437        ).try_into().unwrap();
438        assert_eq!( event.event_type(), PointerDownEvent::EVENT_TYPE );
439    }
440
441    #[test]
442    fn test_pointer_move_event() {
443        let event: PointerMoveEvent = js!(
444            return new PointerEvent( @{PointerMoveEvent::EVENT_TYPE} );
445        ).try_into().unwrap();
446        assert_eq!( event.event_type(), PointerMoveEvent::EVENT_TYPE );
447    }
448
449    #[test]
450    fn test_pointer_up_event() {
451        let event: PointerUpEvent = js!(
452            return new PointerEvent( @{PointerUpEvent::EVENT_TYPE} );
453        ).try_into().unwrap();
454        assert_eq!( event.event_type(), PointerUpEvent::EVENT_TYPE );
455    }
456
457    #[test]
458    fn test_pointer_cancel_event() {
459        let event: PointerCancelEvent = js!(
460            return new PointerEvent( @{PointerCancelEvent::EVENT_TYPE} );
461        ).try_into().unwrap();
462        assert_eq!( event.event_type(), PointerCancelEvent::EVENT_TYPE );
463    }
464
465    #[test]
466    fn test_pointer_out_event() {
467        let event: PointerOutEvent = js!(
468            return new PointerEvent( @{PointerOutEvent::EVENT_TYPE} );
469        ).try_into().unwrap();
470        assert_eq!( event.event_type(), PointerOutEvent::EVENT_TYPE );
471    }
472
473    #[test]
474    fn test_pointer_leave_event() {
475        let event: PointerLeaveEvent = js!(
476            return new PointerEvent( @{PointerLeaveEvent::EVENT_TYPE} );
477        ).try_into().unwrap();
478        assert_eq!( event.event_type(), PointerLeaveEvent::EVENT_TYPE );
479    }
480
481    #[test]
482    fn test_got_pointer_capture_event() {
483        let event: GotPointerCaptureEvent = js!(
484            return new PointerEvent( @{GotPointerCaptureEvent::EVENT_TYPE} );
485        ).try_into().unwrap();
486        assert_eq!( event.event_type(), GotPointerCaptureEvent::EVENT_TYPE );
487    }
488
489    #[test]
490    fn test_lost_pointer_capture_event() {
491        let event: LostPointerCaptureEvent = js!(
492            return new PointerEvent( @{LostPointerCaptureEvent::EVENT_TYPE} );
493        ).try_into().unwrap();
494        assert_eq!( event.event_type(), LostPointerCaptureEvent::EVENT_TYPE );
495    }
496
497    #[test]
498    fn test_pointer_lock_change_event() {
499        let event: PointerLockChangeEvent = js!(
500            return new Event( @{PointerLockChangeEvent::EVENT_TYPE} );
501        ).try_into().unwrap();
502        assert_eq!( event.event_type(), PointerLockChangeEvent::EVENT_TYPE );
503    }
504
505    #[test]
506    fn test_pointer_lock_error_event() {
507        let event: PointerLockErrorEvent = js!(
508            return new Event( @{PointerLockErrorEvent::EVENT_TYPE} );
509        ).try_into().unwrap();
510        assert_eq!( event.event_type(), PointerLockErrorEvent::EVENT_TYPE );
511    }
512}