1use webcore::value::Reference;
2use webcore::try_from::TryInto;
3use webapi::event_target::EventTarget;
4use webapi::event::{IEvent, IUiEvent, UiEvent, Event};
5use webapi::events::keyboard::{ModifierKey, get_event_modifier_state};
6
7pub trait IMouseEvent: IUiEvent {
13 #[inline]
18 fn alt_key( &self ) -> bool {
19 js!(
20 return @{self.as_ref()}.altKey;
21 ).try_into().unwrap()
22 }
23
24 fn button( &self ) -> MouseButton {
29 match js!(
30 return @{self.as_ref()}.button;
31 ).try_into().unwrap() {
32 0 => MouseButton::Left,
33 1 => MouseButton::Wheel,
34 2 => MouseButton::Right,
35 3 => MouseButton::Button4,
36 4 => MouseButton::Button5,
37 _ => unreachable!("Unexpected MouseEvent.button value"),
38 }
39 }
40
41 fn buttons( &self ) -> MouseButtonsState {
46 MouseButtonsState(
47 js!(
48 return @{self.as_ref()}.buttons;
49 ).try_into().unwrap()
50 )
51 }
52
53 #[inline]
58 fn client_x( &self ) -> i32 {
59 js!(
60 return @{self.as_ref()}.clientX;
61 ).try_into().unwrap()
62 }
63
64 #[inline]
69 fn client_y( &self ) -> i32 {
70 js!(
71 return @{self.as_ref()}.clientY;
72 ).try_into().unwrap()
73 }
74
75 #[inline]
80 fn offset_x( &self ) -> f64 {
81 js!(
82 return @{self.as_ref()}.offsetX;
83 ).try_into().unwrap()
84 }
85
86 #[inline]
91 fn offset_y( &self ) -> f64 {
92 js!(
93 return @{self.as_ref()}.offsetY;
94 ).try_into().unwrap()
95 }
96
97 #[inline]
102 fn ctrl_key( &self ) -> bool {
103 js!(
104 return @{self.as_ref()}.ctrlKey;
105 ).try_into().unwrap()
106 }
107
108 #[inline]
113 fn get_modifier_state( &self, key: ModifierKey ) -> bool {
114 get_event_modifier_state( self, key )
115 }
116
117 #[inline]
122 fn meta_key( &self ) -> bool {
123 js!(
124 return @{self.as_ref()}.metaKey;
125 ).try_into().unwrap()
126 }
127
128 #[inline]
134 fn movement_x( &self ) -> i32 {
135 js!(
136 return @{self.as_ref()}.movementX;
137 ).try_into().unwrap()
138 }
139
140 #[inline]
146 fn movement_y( &self ) -> i32 {
147 js!(
148 return @{self.as_ref()}.movementY;
149 ).try_into().unwrap()
150 }
151
152 #[inline]
156 fn region( &self ) -> Option< String > {
157 js!(
158 return @{self.as_ref()}.region;
159 ).try_into().ok()
160 }
161
162 #[inline]
167 fn related_target( &self ) -> Option< EventTarget > {
168 js!(
169 return @{self.as_ref()}.relatedTarget;
170 ).try_into().ok()
171 }
172
173 #[inline]
178 fn screen_x( &self ) -> i32 {
179 js!(
180 return @{self.as_ref()}.screenX;
181 ).try_into().unwrap()
182 }
183
184 #[inline]
189 fn screen_y( &self ) -> i32 {
190 js!(
191 return @{self.as_ref()}.screenY;
192 ).try_into().unwrap()
193 }
194
195 #[inline]
200 fn shift_key( &self ) -> bool {
201 js!(
202 return @{self.as_ref()}.shiftKey;
203 ).try_into().unwrap()
204 }
205}
206
207#[derive(Clone, Copy, Debug, PartialEq, Eq)]
209pub enum MouseButton {
210 Left,
212 Wheel,
214 Right,
216 Button4,
218 Button5,
220 }
223
224#[derive(Copy, Clone, Debug, PartialEq, Eq)]
226pub struct MouseButtonsState(u8);
227
228impl MouseButtonsState {
229 pub fn is_down(&self, button: MouseButton) -> bool {
231 match button {
232 MouseButton::Left => self.0 & 0b1 != 0,
233 MouseButton::Right => self.0 & 0b10 != 0,
234 MouseButton::Wheel => self.0 & 0b100 != 0,
235 MouseButton::Button4 => self.0 & 0b1000 != 0,
236 MouseButton::Button5 => self.0 & 0b1_0000 != 0,
237 }
238 }
239}
240
241#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
247#[reference(instance_of = "MouseEvent")]
248#[reference(subclass_of(Event, UiEvent))]
249pub struct MouseEvent( Reference );
250
251impl IEvent for MouseEvent {}
252impl IUiEvent for MouseEvent {}
253impl IMouseEvent for MouseEvent {}
254
255#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
261#[reference(instance_of = "MouseEvent")]
262#[reference(event = "click")]
263#[reference(subclass_of(Event, UiEvent, MouseEvent))]
264pub struct ClickEvent( Reference );
265
266impl IEvent for ClickEvent {}
267impl IUiEvent for ClickEvent {}
268impl IMouseEvent for ClickEvent {}
269
270#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
276#[reference(instance_of = "MouseEvent")]
277#[reference(event = "auxclick")]
278#[reference(subclass_of(Event, UiEvent, MouseEvent))]
279pub struct AuxClickEvent( Reference );
280
281impl IEvent for AuxClickEvent {}
282impl IUiEvent for AuxClickEvent {}
283impl IMouseEvent for AuxClickEvent {}
284
285#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
291#[reference(instance_of = "MouseEvent")]
292#[reference(event = "contextmenu")]
293#[reference(subclass_of(Event, UiEvent, MouseEvent))]
294pub struct ContextMenuEvent( Reference );
295
296impl IEvent for ContextMenuEvent {}
297impl IUiEvent for ContextMenuEvent {}
298impl IMouseEvent for ContextMenuEvent {}
299
300#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
307#[reference(instance_of = "MouseEvent")]
308#[reference(event = "dblclick")]
309#[reference(subclass_of(Event, UiEvent, MouseEvent))]
310pub struct DoubleClickEvent( Reference );
311
312impl IEvent for DoubleClickEvent {}
313impl IUiEvent for DoubleClickEvent {}
314impl IMouseEvent for DoubleClickEvent {}
315
316#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
322#[reference(instance_of = "MouseEvent")]
323#[reference(event = "mousedown")]
324#[reference(subclass_of(Event, UiEvent, MouseEvent))]
325pub struct MouseDownEvent( Reference );
326
327impl IEvent for MouseDownEvent {}
328impl IUiEvent for MouseDownEvent {}
329impl IMouseEvent for MouseDownEvent {}
330
331#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
337#[reference(instance_of = "MouseEvent")]
338#[reference(event = "mouseup")]
339#[reference(subclass_of(Event, UiEvent, MouseEvent))]
340pub struct MouseUpEvent( Reference );
341
342impl IEvent for MouseUpEvent {}
343impl IUiEvent for MouseUpEvent {}
344impl IMouseEvent for MouseUpEvent {}
345
346#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
352#[reference(instance_of = "MouseEvent")]
353#[reference(event = "mousemove")]
354#[reference(subclass_of(Event, UiEvent, MouseEvent))]
355pub struct MouseMoveEvent( Reference );
356
357impl IEvent for MouseMoveEvent {}
358impl IUiEvent for MouseMoveEvent {}
359impl IMouseEvent for MouseMoveEvent {}
360
361#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
367#[reference(instance_of = "MouseEvent")]
368#[reference(event = "mouseover")]
369#[reference(subclass_of(Event, UiEvent, MouseEvent))]
370pub struct MouseOverEvent( Reference );
371
372impl IEvent for MouseOverEvent {}
373impl IUiEvent for MouseOverEvent {}
374impl IMouseEvent for MouseOverEvent {}
375
376#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
382#[reference(instance_of = "MouseEvent")]
383#[reference(event = "mouseout")]
384#[reference(subclass_of(Event, UiEvent, MouseEvent))]
385pub struct MouseOutEvent( Reference );
386
387impl IEvent for MouseOutEvent {}
388impl IUiEvent for MouseOutEvent {}
389impl IMouseEvent for MouseOutEvent {}
390
391#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
397#[reference(instance_of = "MouseEvent")]
398#[reference(event = "mouseenter")]
399#[reference(subclass_of(Event, UiEvent, MouseEvent))]
400pub struct MouseEnterEvent( Reference );
401
402impl IEvent for MouseEnterEvent {}
403impl IUiEvent for MouseEnterEvent {}
404impl IMouseEvent for MouseEnterEvent {}
405
406#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
412#[reference(instance_of = "MouseEvent")]
413#[reference(event = "mouseleave")]
414#[reference(subclass_of(Event, UiEvent, MouseEvent))]
415pub struct MouseLeaveEvent( Reference );
416
417impl IEvent for MouseLeaveEvent {}
418impl IUiEvent for MouseLeaveEvent {}
419impl IMouseEvent for MouseLeaveEvent {}
420
421#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
427#[reference(instance_of = "MouseEvent")]
428#[reference(event = "wheel")]
429#[reference(subclass_of(Event, UiEvent, MouseEvent))]
430pub struct MouseWheelEvent( Reference );
431
432impl IEvent for MouseWheelEvent {}
433impl IUiEvent for MouseWheelEvent {}
434impl IMouseEvent for MouseWheelEvent {}
435
436impl MouseWheelEvent {
437 pub fn delta_x(&self) -> f64 {
442 js! (
443 return @{self}.deltaX;
444 ).try_into().unwrap()
445 }
446
447 pub fn delta_y(&self) -> f64 {
452 js! (
453 return @{self}.deltaY;
454 ).try_into().unwrap()
455 }
456
457 pub fn delta_z(&self) -> f64 {
462 js! (
463 return @{self}.deltaZ;
464 ).try_into().unwrap()
465 }
466
467 pub fn delta_mode(&self) -> MouseWheelDeltaMode {
472 let mode: u32 = js! (
473 return @{self}.deltaMode;
474 ).try_into().unwrap();
475 match mode {
476 0 => MouseWheelDeltaMode::Pixel,
477 1 => MouseWheelDeltaMode::Line,
478 2 => MouseWheelDeltaMode::Page,
479 _ => unreachable!()
480 }
481 }
482}
483
484#[derive(Clone, Copy, Debug, PartialEq, Eq)]
488pub enum MouseWheelDeltaMode {
489 Pixel,
492 Line,
495 Page
498}
499
500#[cfg(all(test, feature = "web_test"))]
501mod tests {
502 use super::*;
503 use webapi::event::ConcreteEvent;
504
505 #[test]
506 fn test_mouse_event() {
507 let event: MouseEvent = js!(
508 return new MouseEvent(
509 @{ClickEvent::EVENT_TYPE},
510 {
511 altKey: false,
512 button: 2,
513 buttons: 6,
514 clientX: 3,
515 clientY: 4,
516 ctrlKey: true,
517 metaKey: false,
518 screenX: 1,
519 screenY: 2,
520 shiftKey: true
521 }
522 );
523 ).try_into().unwrap();
524 assert_eq!( event.event_type(), ClickEvent::EVENT_TYPE );
525 assert_eq!( event.alt_key(), false );
526 assert_eq!( event.button(), MouseButton::Right );
527 assert!( !event.buttons().is_down( MouseButton::Left ) );
528 assert!( event.buttons().is_down( MouseButton::Right ) );
529 assert!( event.buttons().is_down( MouseButton::Wheel ) );
530 assert_eq!( event.client_x(), 3 );
531 assert_eq!( event.client_y(), 4 );
532 assert!( event.ctrl_key() );
533 assert!( !event.get_modifier_state( ModifierKey::Alt ) );
534 assert!( event.get_modifier_state( ModifierKey::Ctrl ) );
535 assert!( event.get_modifier_state( ModifierKey::Shift ) );
536 assert!( !event.meta_key() );
537 assert_eq!( event.movement_x(), 0 );
538 assert_eq!( event.movement_y(), 0 );
539 assert!( event.region().is_none() );
540 assert!( event.related_target().is_none() );
541 assert_eq!( event.screen_x(), 1 );
542 assert_eq!( event.screen_y(), 2 );
543 assert!( event.shift_key() );
544 }
545
546 #[test]
547 fn test_click_event() {
548 let event: ClickEvent = js!(
549 return new MouseEvent( @{ClickEvent::EVENT_TYPE} );
550 ).try_into().unwrap();
551 assert_eq!( event.event_type(), ClickEvent::EVENT_TYPE );
552 }
553
554 #[test]
555 fn test_aux_click_event() {
556 let event: AuxClickEvent = js!(
557 return new MouseEvent( @{AuxClickEvent::EVENT_TYPE} );
558 ).try_into()
559 .unwrap();
560 assert_eq!( event.event_type(), AuxClickEvent::EVENT_TYPE );
561 }
562
563 #[test]
564 fn test_context_menu_event() {
565 let event: ContextMenuEvent = js!(
566 return new MouseEvent( @{ContextMenuEvent::EVENT_TYPE} );
567 ).try_into().unwrap();
568 assert_eq!( event.event_type(), ContextMenuEvent::EVENT_TYPE );
569 }
570
571 #[test]
572 fn test_double_click_event() {
573 let event: DoubleClickEvent = js!(
574 return new MouseEvent( @{DoubleClickEvent::EVENT_TYPE} );
575 ).try_into().unwrap();
576 assert_eq!( event.event_type(), DoubleClickEvent::EVENT_TYPE );
577 }
578
579 #[test]
580 fn test_mouse_down_event() {
581 let event: MouseDownEvent = js!(
582 return new MouseEvent( @{MouseDownEvent::EVENT_TYPE} );
583 ).try_into().unwrap();
584 assert_eq!( event.event_type(), MouseDownEvent::EVENT_TYPE );
585 }
586
587 #[test]
588 fn test_mouse_up_event() {
589 let event: MouseUpEvent = js!(
590 return new MouseEvent( @{MouseUpEvent::EVENT_TYPE} );
591 ).try_into().unwrap();
592 assert_eq!( event.event_type(), MouseUpEvent::EVENT_TYPE );
593 }
594
595 #[test]
596 fn test_mouse_move_event() {
597 let event: MouseMoveEvent = js!(
598 return new MouseEvent( @{MouseMoveEvent::EVENT_TYPE} );
599 ).try_into().unwrap();
600 assert_eq!( event.event_type(), MouseMoveEvent::EVENT_TYPE );
601 }
602
603 #[test]
604 fn test_mouse_over_event() {
605 let event: MouseOverEvent = js!(
606 return new MouseEvent( @{MouseOverEvent::EVENT_TYPE} );
607 ).try_into().unwrap();
608 assert_eq!( event.event_type(), MouseOverEvent::EVENT_TYPE );
609 }
610
611 #[test]
612 fn test_mouse_out_event() {
613 let event: MouseOutEvent = js!(
614 return new MouseEvent( @{MouseOutEvent::EVENT_TYPE} );
615 ).try_into().unwrap();
616 assert_eq!( event.event_type(), MouseOutEvent::EVENT_TYPE );
617 }
618
619 #[test]
620 fn test_mouse_enter_event() {
621 let event: MouseEnterEvent = js!(
622 return new MouseEvent( @{MouseEnterEvent::EVENT_TYPE} );
623 ).try_into()
624 .unwrap();
625 assert_eq!( event.event_type(), MouseEnterEvent::EVENT_TYPE );
626 }
627
628 #[test]
629 fn test_mouse_leave_event() {
630 let event: MouseLeaveEvent = js!(
631 return new MouseEvent( @{MouseLeaveEvent::EVENT_TYPE} );
632 ).try_into()
633 .unwrap();
634 assert_eq!( event.event_type(), MouseLeaveEvent::EVENT_TYPE );
635 }
636
637 #[test]
638 fn test_mouse_wheel_event() {
639 let event: MouseWheelEvent = js!(
640 return new MouseEvent( @{MouseWheelEvent::EVENT_TYPE} );
641 ).try_into()
642 .unwrap();
643 assert_eq!( event.event_type(), MouseWheelEvent::EVENT_TYPE );
644 }
645}