Web: Use mouse events instead of pointer events if the latter isn't supported (#1630)

* Fixed Safari not getting mouse events

* Edited changelog

* Addressed compiler warnings

Co-authored-by: Ryan G <ryanisaacg@users.noreply.github.com>
This commit is contained in:
josh65536 2020-08-04 21:39:09 -04:00 committed by GitHub
parent 7a49c88200
commit 05fdcb5b27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 109 additions and 38 deletions

View file

@ -10,6 +10,7 @@
- On android added support for `run_return`. - On android added support for `run_return`.
- On MacOS, Fixed fullscreen and dialog support for `run_return`. - On MacOS, Fixed fullscreen and dialog support for `run_return`.
- On Windows, fix bug where we'd try to emit `MainEventsCleared` events during nested win32 event loops. - On Windows, fix bug where we'd try to emit `MainEventsCleared` events during nested win32 event loops.
- On Web, use mouse events if pointer events aren't supported. This affects Safari.
- On Windows, `set_ime_position` is now a no-op instead of a runtime crash. - On Windows, `set_ime_position` is now a no-op instead of a runtime crash.
- On Android, `set_fullscreen` is now a no-op instead of a runtime crash. - On Android, `set_fullscreen` is now a no-op instead of a runtime crash.
- On iOS and Android, `set_inner_size` is now a no-op instead of a runtime crash. - On iOS and Android, `set_inner_size` is now a no-op instead of a runtime crash.

View file

@ -9,8 +9,8 @@ use std::rc::Rc;
use wasm_bindgen::{closure::Closure, JsCast}; use wasm_bindgen::{closure::Closure, JsCast};
use web_sys::{ use web_sys::{
Event, FocusEvent, HtmlCanvasElement, KeyboardEvent, MediaQueryListEvent, PointerEvent, Event, FocusEvent, HtmlCanvasElement, KeyboardEvent, MediaQueryListEvent, MouseEvent,
WheelEvent, PointerEvent, WheelEvent,
}; };
pub struct Canvas { pub struct Canvas {
@ -24,8 +24,14 @@ pub struct Canvas {
on_cursor_leave: Option<Closure<dyn FnMut(PointerEvent)>>, on_cursor_leave: Option<Closure<dyn FnMut(PointerEvent)>>,
on_cursor_enter: Option<Closure<dyn FnMut(PointerEvent)>>, on_cursor_enter: Option<Closure<dyn FnMut(PointerEvent)>>,
on_cursor_move: Option<Closure<dyn FnMut(PointerEvent)>>, on_cursor_move: Option<Closure<dyn FnMut(PointerEvent)>>,
on_mouse_press: Option<Closure<dyn FnMut(PointerEvent)>>, on_pointer_press: Option<Closure<dyn FnMut(PointerEvent)>>,
on_mouse_release: Option<Closure<dyn FnMut(PointerEvent)>>, on_pointer_release: Option<Closure<dyn FnMut(PointerEvent)>>,
// Fallback events when pointer event support is missing
on_mouse_leave: Option<Closure<dyn FnMut(MouseEvent)>>,
on_mouse_enter: Option<Closure<dyn FnMut(MouseEvent)>>,
on_mouse_move: Option<Closure<dyn FnMut(MouseEvent)>>,
on_mouse_press: Option<Closure<dyn FnMut(MouseEvent)>>,
on_mouse_release: Option<Closure<dyn FnMut(MouseEvent)>>,
on_mouse_wheel: Option<Closure<dyn FnMut(WheelEvent)>>, on_mouse_wheel: Option<Closure<dyn FnMut(WheelEvent)>>,
on_fullscreen_change: Option<Closure<dyn FnMut(Event)>>, on_fullscreen_change: Option<Closure<dyn FnMut(Event)>>,
wants_fullscreen: Rc<RefCell<bool>>, wants_fullscreen: Rc<RefCell<bool>>,
@ -76,8 +82,13 @@ impl Canvas {
on_cursor_leave: None, on_cursor_leave: None,
on_cursor_enter: None, on_cursor_enter: None,
on_cursor_move: None, on_cursor_move: None,
on_mouse_release: None, on_pointer_release: None,
on_pointer_press: None,
on_mouse_leave: None,
on_mouse_enter: None,
on_mouse_move: None,
on_mouse_press: None, on_mouse_press: None,
on_mouse_release: None,
on_mouse_wheel: None, on_mouse_wheel: None,
on_fullscreen_change: None, on_fullscreen_change: None,
wants_fullscreen: Rc::new(RefCell::new(false)), wants_fullscreen: Rc::new(RefCell::new(false)),
@ -180,25 +191,40 @@ impl Canvas {
where where
F: 'static + FnMut(i32), F: 'static + FnMut(i32),
{ {
self.on_cursor_leave = Some(self.add_event("pointerout", move |event: PointerEvent| { if has_pointer_event() {
self.on_cursor_leave =
Some(self.add_event("pointerout", move |event: PointerEvent| {
handler(event.pointer_id()); handler(event.pointer_id());
})); }));
} else {
self.on_mouse_leave = Some(self.add_event("mouseout", move |_: MouseEvent| {
handler(0);
}));
}
} }
pub fn on_cursor_enter<F>(&mut self, mut handler: F) pub fn on_cursor_enter<F>(&mut self, mut handler: F)
where where
F: 'static + FnMut(i32), F: 'static + FnMut(i32),
{ {
self.on_cursor_enter = Some(self.add_event("pointerover", move |event: PointerEvent| { if has_pointer_event() {
self.on_cursor_enter =
Some(self.add_event("pointerover", move |event: PointerEvent| {
handler(event.pointer_id()); handler(event.pointer_id());
})); }));
} else {
self.on_mouse_enter = Some(self.add_event("mouseover", move |_: MouseEvent| {
handler(0);
}));
}
} }
pub fn on_mouse_release<F>(&mut self, mut handler: F) pub fn on_mouse_release<F>(&mut self, mut handler: F)
where where
F: 'static + FnMut(i32, MouseButton, ModifiersState), F: 'static + FnMut(i32, MouseButton, ModifiersState),
{ {
self.on_mouse_release = Some(self.add_user_event( if has_pointer_event() {
self.on_pointer_release = Some(self.add_user_event(
"pointerup", "pointerup",
move |event: PointerEvent| { move |event: PointerEvent| {
handler( handler(
@ -208,13 +234,24 @@ impl Canvas {
); );
}, },
)); ));
} else {
self.on_mouse_release =
Some(self.add_user_event("mouseup", move |event: MouseEvent| {
handler(
0,
event::mouse_button(&event),
event::mouse_modifiers(&event),
);
}));
}
} }
pub fn on_mouse_press<F>(&mut self, mut handler: F) pub fn on_mouse_press<F>(&mut self, mut handler: F)
where where
F: 'static + FnMut(i32, MouseButton, ModifiersState), F: 'static + FnMut(i32, MouseButton, ModifiersState),
{ {
self.on_mouse_press = Some(self.add_user_event( if has_pointer_event() {
self.on_pointer_press = Some(self.add_user_event(
"pointerdown", "pointerdown",
move |event: PointerEvent| { move |event: PointerEvent| {
handler( handler(
@ -224,19 +261,40 @@ impl Canvas {
); );
}, },
)); ));
} else {
self.on_mouse_press =
Some(self.add_user_event("mousedown", move |event: MouseEvent| {
handler(
0,
event::mouse_button(&event),
event::mouse_modifiers(&event),
);
}));
}
} }
pub fn on_cursor_move<F>(&mut self, mut handler: F) pub fn on_cursor_move<F>(&mut self, mut handler: F)
where where
F: 'static + FnMut(i32, PhysicalPosition<f64>, ModifiersState), F: 'static + FnMut(i32, PhysicalPosition<f64>, ModifiersState),
{ {
self.on_cursor_move = Some(self.add_event("pointermove", move |event: PointerEvent| { if has_pointer_event() {
self.on_cursor_move =
Some(self.add_event("pointermove", move |event: PointerEvent| {
handler( handler(
event.pointer_id(), event.pointer_id(),
event::mouse_position(&event).to_physical(super::scale_factor()), event::mouse_position(&event).to_physical(super::scale_factor()),
event::mouse_modifiers(&event), event::mouse_modifiers(&event),
); );
})); }));
} else {
self.on_mouse_move = Some(self.add_event("mousemove", move |event: MouseEvent| {
handler(
0,
event::mouse_position(&event).to_physical(super::scale_factor()),
event::mouse_modifiers(&event),
);
}));
}
} }
pub fn on_mouse_wheel<F>(&mut self, mut handler: F) pub fn on_mouse_wheel<F>(&mut self, mut handler: F)
@ -334,3 +392,15 @@ impl Canvas {
super::is_fullscreen(&self.raw) super::is_fullscreen(&self.raw)
} }
} }
/// Returns whether pointer events are supported.
/// Used to decide whether to use pointer events
/// or plain mouse events. Note that Safari
/// doesn't support pointer events now.
fn has_pointer_event() -> bool {
if let Some(window) = web_sys::window() {
window.get("PointerEvent").is_some()
} else {
false
}
}