api: overhaul pointer API
- Rename `CursorMoved` to `PointerMoved`. - Rename `CursorEntered` to `PointerEntered`. - Rename `CursorLeft` to `PointerLeft`. - Rename `MouseInput` to `PointerButton`. - Add `position` to every `PointerEvent`. - Remove `Touch`, which is folded into the `Pointer*` events. - New `PointerType` added to `PointerEntered` and `PointerLeft`, signifying which pointer type is the source of this event. - New `PointerSource` added to `PointerMoved`, similar to `PointerType` but holding additional data. - New `ButtonSource` added to `PointerButton`, similar to `PointerType` but holding pointer type specific buttons. Use `ButtonSource::mouse_button()` to easily normalize any pointer button type to a generic mouse button. - In the same spirit rename `DeviceEvent::MouseMotion` to `PointerMotion`. - Remove `Force::Calibrated::altitude_angle`. Fixes #3833. Fixes #883. Fixes #336. Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
This commit is contained in:
parent
32cd1ad9a7
commit
eccd9e415d
25 changed files with 1236 additions and 869 deletions
|
|
@ -1,5 +1,7 @@
|
|||
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId(u32);
|
||||
use crate::event::FingerId as RootFingerId;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId(pub(crate) u32);
|
||||
|
||||
impl DeviceId {
|
||||
pub fn new(pointer_id: i32) -> Option<Self> {
|
||||
|
|
@ -34,3 +36,9 @@ impl FingerId {
|
|||
self.primary
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FingerId> for RootFingerId {
|
||||
fn from(id: FingerId) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ impl Shared {
|
|||
|
||||
runner.send_event(Event::DeviceEvent {
|
||||
device_id,
|
||||
event: DeviceEvent::Button { button: button.to_id(), state },
|
||||
event: DeviceEvent::Button { button: button.to_id().into(), state },
|
||||
});
|
||||
|
||||
return;
|
||||
|
|
@ -310,7 +310,7 @@ impl Shared {
|
|||
|
||||
Event::DeviceEvent {
|
||||
device_id,
|
||||
event: DeviceEvent::MouseMotion { delta: (delta.x, delta.y) },
|
||||
event: DeviceEvent::PointerMotion { delta: (delta.x, delta.y) },
|
||||
}
|
||||
}));
|
||||
}),
|
||||
|
|
@ -346,7 +346,7 @@ impl Shared {
|
|||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: DeviceId::new(event.pointer_id()).map(RootDeviceId),
|
||||
event: DeviceEvent::Button {
|
||||
button: button.to_id(),
|
||||
button: button.to_id().into(),
|
||||
state: ElementState::Pressed,
|
||||
},
|
||||
});
|
||||
|
|
@ -365,7 +365,7 @@ impl Shared {
|
|||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: DeviceId::new(event.pointer_id()).map(RootDeviceId),
|
||||
event: DeviceEvent::Button {
|
||||
button: button.to_id(),
|
||||
button: button.to_id().into(),
|
||||
state: ElementState::Released,
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ use super::window::WindowId;
|
|||
use super::{backend, runner, EventLoopProxy};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::{
|
||||
DeviceId as RootDeviceId, ElementState, Event, FingerId as RootFingerId, KeyEvent, Touch,
|
||||
TouchPhase, WindowEvent,
|
||||
DeviceId as RootDeviceId, ElementState, Event, KeyEvent, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::event_loop::{
|
||||
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
||||
|
|
@ -200,12 +199,12 @@ impl ActiveEventLoop {
|
|||
);
|
||||
|
||||
let has_focus = canvas.has_focus.clone();
|
||||
canvas.on_cursor_leave({
|
||||
canvas.on_pointer_leave({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id| {
|
||||
move |active_modifiers, device_id, position, kind| {
|
||||
let focus = (has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
|
|
@ -214,23 +213,23 @@ impl ActiveEventLoop {
|
|||
}
|
||||
});
|
||||
|
||||
let pointer = pointer_id.map(|device_id| Event::WindowEvent {
|
||||
runner.send_events(focus.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorLeft { device_id: device_id.map(RootDeviceId) },
|
||||
});
|
||||
|
||||
if focus.is_some() || pointer.is_some() {
|
||||
runner.send_events(focus.into_iter().chain(pointer))
|
||||
}
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
position: Some(position),
|
||||
kind,
|
||||
},
|
||||
})))
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_cursor_enter({
|
||||
canvas.on_pointer_enter({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id| {
|
||||
move |active_modifiers, device_id, position, kind| {
|
||||
let focus = (has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
|
|
@ -239,41 +238,41 @@ impl ActiveEventLoop {
|
|||
}
|
||||
});
|
||||
|
||||
let pointer = pointer_id.map(|device_id| Event::WindowEvent {
|
||||
runner.send_events(focus.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorEntered { device_id: device_id.map(RootDeviceId) },
|
||||
});
|
||||
|
||||
if focus.is_some() || pointer.is_some() {
|
||||
runner.send_events(focus.into_iter().chain(pointer))
|
||||
}
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
position,
|
||||
kind,
|
||||
},
|
||||
})))
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_cursor_move(
|
||||
canvas.on_pointer_move(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id, events| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(events.flat_map(|position| {
|
||||
move |pointer_id, events| {
|
||||
runner.send_events(events.flat_map(|(active_modifiers, position, source)| {
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
|
||||
iter::once(Event::WindowEvent {
|
||||
let modifiers = (has_focus.get() && modifiers.get() != active_modifiers)
|
||||
.then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
})
|
||||
})));
|
||||
event: WindowEvent::PointerMoved { device_id, position, source },
|
||||
}))
|
||||
}));
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -281,40 +280,7 @@ impl ActiveEventLoop {
|
|||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, events| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(events.map(
|
||||
|(location, force)| Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Moved,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers,
|
||||
device_id,
|
||||
position: crate::dpi::PhysicalPosition<f64>,
|
||||
buttons,
|
||||
button| {
|
||||
move |active_modifiers, device_id, position, state, button| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
|
|
@ -326,36 +292,48 @@ impl ActiveEventLoop {
|
|||
|
||||
let device_id = device_id.map(RootDeviceId);
|
||||
|
||||
let state = if buttons.contains(button.into()) {
|
||||
ElementState::Pressed
|
||||
} else {
|
||||
ElementState::Released
|
||||
};
|
||||
|
||||
// A chorded button event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput { device_id, state, button },
|
||||
},
|
||||
]));
|
||||
runner.send_events(modifiers.into_iter().chain([Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::PointerButton { device_id, state, position, button },
|
||||
}]));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
canvas.on_mouse_press(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
canvas.on_pointer_press({
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id, position, button| {
|
||||
let modifiers = (modifiers.get() != active_modifiers).then(|| {
|
||||
move |active_modifiers, pointer_id, position, button| {
|
||||
let modifiers = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button,
|
||||
},
|
||||
})));
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_pointer_release({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id, position, button| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
|
|
@ -363,123 +341,19 @@ impl ActiveEventLoop {
|
|||
}
|
||||
});
|
||||
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
|
||||
// A mouse down event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
device_id,
|
||||
state: ElementState::Pressed,
|
||||
button,
|
||||
},
|
||||
},
|
||||
]));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, location, force| {
|
||||
let modifiers = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Started,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)))
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
canvas.on_mouse_release(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id, position, button| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
|
||||
// A mouse up event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
device_id,
|
||||
state: ElementState::Released,
|
||||
button,
|
||||
},
|
||||
},
|
||||
]));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner_touch = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, location, force| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner_touch.send_events(modifiers.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Ended,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)));
|
||||
}
|
||||
},
|
||||
);
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button,
|
||||
},
|
||||
})));
|
||||
}
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
|
@ -505,20 +379,6 @@ impl ActiveEventLoop {
|
|||
)));
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_touch_cancel(move |device_id, finger_id, location, force| {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Cancelled,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_dark_mode(move |is_dark_mode| {
|
||||
let theme = if is_dark_mode { Theme::Dark } else { Theme::Light };
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use web_sys::{
|
|||
};
|
||||
|
||||
use super::super::cursor::CursorHandler;
|
||||
use super::super::event::{DeviceId, FingerId};
|
||||
use super::super::event::DeviceId;
|
||||
use super::super::main_thread::MainThreadMarker;
|
||||
use super::super::WindowId;
|
||||
use super::animation_frame::AnimationFrameHandler;
|
||||
|
|
@ -20,10 +20,12 @@ use super::event_handle::EventListenerHandle;
|
|||
use super::intersection_handle::IntersectionObserverHandle;
|
||||
use super::media_query_handle::MediaQueryListHandle;
|
||||
use super::pointer::PointerHandler;
|
||||
use super::{event, fullscreen, ButtonsState, ResizeScaleHandle};
|
||||
use super::{event, fullscreen, ResizeScaleHandle};
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
|
||||
use crate::error::RequestError;
|
||||
use crate::event::{Force, MouseButton, MouseScrollDelta, SurfaceSizeWriter};
|
||||
use crate::event::{
|
||||
ButtonSource, ElementState, MouseScrollDelta, PointerKind, PointerSource, SurfaceSizeWriter,
|
||||
};
|
||||
use crate::keyboard::{Key, KeyLocation, ModifiersState, PhysicalKey};
|
||||
use crate::platform_impl::Fullscreen;
|
||||
use crate::window::{WindowAttributes, WindowId as RootWindowId};
|
||||
|
|
@ -328,83 +330,62 @@ impl Canvas {
|
|||
}));
|
||||
}
|
||||
|
||||
pub fn on_cursor_leave<F>(&self, handler: F)
|
||||
pub fn on_pointer_leave<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_leave(&self.common, handler)
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_leave(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_cursor_enter<F>(&self, handler: F)
|
||||
pub fn on_pointer_enter<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_enter(&self.common, handler)
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_enter(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_mouse_release<M, T>(&self, mouse_handler: M, touch_handler: T)
|
||||
pub fn on_pointer_release<C>(&self, handler: C)
|
||||
where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_mouse_release(
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_release(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_pointer_press<C>(&self, handler: C)
|
||||
where
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_press(
|
||||
&self.common,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_mouse_press<M, T>(&self, mouse_handler: M, touch_handler: T)
|
||||
where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_mouse_press(
|
||||
&self.common,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
handler,
|
||||
Rc::clone(&self.prevent_default),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_cursor_move<M, T, B>(&self, mouse_handler: M, touch_handler: T, button_handler: B)
|
||||
pub fn on_pointer_move<C, B>(&self, cursor_handler: C, button_handler: B)
|
||||
where
|
||||
M: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, &mut dyn Iterator<Item = PhysicalPosition<f64>>),
|
||||
T: 'static
|
||||
C: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
FingerId,
|
||||
&mut dyn Iterator<Item = (PhysicalPosition<f64>, Force)>,
|
||||
&mut dyn Iterator<Item = (ModifiersState, PhysicalPosition<f64>, PointerSource)>,
|
||||
),
|
||||
B: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
PhysicalPosition<f64>,
|
||||
ButtonsState,
|
||||
MouseButton,
|
||||
ElementState,
|
||||
ButtonSource,
|
||||
),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_move(
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_move(
|
||||
&self.common,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
cursor_handler,
|
||||
button_handler,
|
||||
Rc::clone(&self.prevent_default),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_touch_cancel<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_touch_cancel(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_mouse_wheel<F>(&self, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(MouseScrollDelta, ModifiersState),
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ use wasm_bindgen::prelude::wasm_bindgen;
|
|||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use web_sys::{KeyboardEvent, MouseEvent, Navigator, PointerEvent, WheelEvent};
|
||||
|
||||
use super::super::FingerId;
|
||||
use super::Engine;
|
||||
use crate::event::{MouseButton, MouseScrollDelta};
|
||||
use crate::event::{MouseButton, MouseScrollDelta, PointerKind};
|
||||
use crate::keyboard::{Key, KeyLocation, ModifiersState, NamedKey, PhysicalKey};
|
||||
|
||||
bitflags::bitflags! {
|
||||
|
|
@ -68,14 +69,14 @@ pub fn mouse_button(event: &MouseEvent) -> Option<MouseButton> {
|
|||
}
|
||||
|
||||
impl MouseButton {
|
||||
pub fn to_id(self) -> u32 {
|
||||
pub fn to_id(self) -> u16 {
|
||||
match self {
|
||||
MouseButton::Left => 0,
|
||||
MouseButton::Right => 1,
|
||||
MouseButton::Middle => 2,
|
||||
MouseButton::Back => 3,
|
||||
MouseButton::Forward => 4,
|
||||
MouseButton::Other(value) => value.into(),
|
||||
MouseButton::Other(value) => value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -160,6 +161,14 @@ pub fn mouse_scroll_delta(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pointer_type(event: &PointerEvent, pointer_id: i32) -> PointerKind {
|
||||
match event.pointer_type().as_str() {
|
||||
"mouse" => PointerKind::Mouse,
|
||||
"touch" => PointerKind::Touch(FingerId::new(pointer_id, event.is_primary()).into()),
|
||||
_ => PointerKind::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn key_code(event: &KeyboardEvent) -> PhysicalKey {
|
||||
let code = event.code();
|
||||
PhysicalKey::from_key_code_attribute_value(&code)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ use wasm_bindgen::JsCast;
|
|||
use web_sys::{Document, HtmlCanvasElement, Navigator, PageTransitionEvent, VisibilityState};
|
||||
|
||||
pub use self::canvas::{Canvas, Style};
|
||||
pub use self::event::ButtonsState;
|
||||
pub use self::event_handle::EventListenerHandle;
|
||||
pub use self::resize_scaling::ResizeScaleHandle;
|
||||
pub use self::schedule::Schedule;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use event::ButtonsState;
|
||||
use web_sys::PointerEvent;
|
||||
|
||||
use super::super::event::{DeviceId, FingerId};
|
||||
use super::super::event::DeviceId;
|
||||
use super::canvas::Common;
|
||||
use super::event;
|
||||
use super::event_handle::EventListenerHandle;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::event::{Force, MouseButton};
|
||||
use crate::event::{ButtonSource, ElementState, Force, PointerKind, PointerSource};
|
||||
use crate::keyboard::ModifiersState;
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -34,88 +33,78 @@ impl PointerHandler {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn on_cursor_leave<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
pub fn on_pointer_leave<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_cursor_leave =
|
||||
Some(canvas_common.add_event("pointerout", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
|
||||
// touch events are handled separately
|
||||
// handling them here would produce duplicate mouse events, inconsistent with
|
||||
// other platforms.
|
||||
let device_id =
|
||||
(event.pointer_type() != "touch").then(|| DeviceId::new(event.pointer_id()));
|
||||
|
||||
handler(modifiers, device_id);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = DeviceId::new(pointer_id);
|
||||
let position =
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window));
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
handler(modifiers, device_id, position, kind);
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_cursor_enter<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
pub fn on_pointer_enter<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_cursor_enter =
|
||||
Some(canvas_common.add_event("pointerover", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
|
||||
// touch events are handled separately
|
||||
// handling them here would produce duplicate mouse events, inconsistent with
|
||||
// other platforms.
|
||||
let device_id =
|
||||
(event.pointer_type() != "touch").then(|| DeviceId::new(event.pointer_id()));
|
||||
|
||||
handler(modifiers, device_id);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = DeviceId::new(pointer_id);
|
||||
let position =
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window));
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
handler(modifiers, device_id, position, kind);
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_mouse_release<M, T>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
) where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
pub fn on_pointer_release<C>(&mut self, canvas_common: &Common, mut handler: C)
|
||||
where
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_pointer_release =
|
||||
Some(canvas_common.add_event("pointerup", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_id = event.pointer_id();
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
|
||||
match event.pointer_type().as_str() {
|
||||
"touch" => {
|
||||
let pointer_id = event.pointer_id();
|
||||
touch_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
)
|
||||
let button = event::mouse_button(&event).expect("no mouse button pressed");
|
||||
|
||||
let source = match kind {
|
||||
PointerKind::Mouse => ButtonSource::Mouse(button),
|
||||
PointerKind::Touch(finger_id) => ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
_ => mouse_handler(
|
||||
modifiers,
|
||||
DeviceId::new(event.pointer_id()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_button(&event).expect("no mouse button released"),
|
||||
),
|
||||
}
|
||||
PointerKind::Unknown => ButtonSource::Unknown(button.to_id()),
|
||||
};
|
||||
|
||||
handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
source,
|
||||
)
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_mouse_press<M, T>(
|
||||
pub fn on_pointer_press<C>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
mut handler: C,
|
||||
prevent_default: Rc<Cell<bool>>,
|
||||
) where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
let canvas = canvas_common.raw().clone();
|
||||
|
|
@ -129,75 +118,65 @@ impl PointerHandler {
|
|||
}
|
||||
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_type = &event.pointer_type();
|
||||
let pointer_id = event.pointer_id();
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
let button = event::mouse_button(&event).expect("no mouse button pressed");
|
||||
|
||||
match pointer_type.as_str() {
|
||||
"touch" => {
|
||||
let pointer_id = event.pointer_id();
|
||||
touch_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
let source = match kind {
|
||||
PointerKind::Mouse => {
|
||||
// Error is swallowed here since the error would occur every time the
|
||||
// mouse is clicked when the cursor is
|
||||
// grabbed, and there is probably not a
|
||||
// situation where this could fail, that we
|
||||
// care if it fails.
|
||||
let _e = canvas.set_pointer_capture(pointer_id);
|
||||
|
||||
ButtonSource::Mouse(button)
|
||||
},
|
||||
_ => {
|
||||
let pointer_id = event.pointer_id();
|
||||
|
||||
mouse_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_button(&event).expect("no mouse button pressed"),
|
||||
);
|
||||
|
||||
if pointer_type == "mouse" {
|
||||
// Error is swallowed here since the error would occur every time the
|
||||
// mouse is clicked when the cursor is
|
||||
// grabbed, and there is probably not a
|
||||
// situation where this could fail, that we
|
||||
// care if it fails.
|
||||
let _e = canvas.set_pointer_capture(pointer_id);
|
||||
}
|
||||
PointerKind::Touch(finger_id) => ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
}
|
||||
PointerKind::Unknown => ButtonSource::Unknown(button.to_id()),
|
||||
};
|
||||
|
||||
handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
source,
|
||||
)
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_cursor_move<M, T, B>(
|
||||
pub fn on_pointer_move<C, B>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
mut cursor_handler: C,
|
||||
mut button_handler: B,
|
||||
prevent_default: Rc<Cell<bool>>,
|
||||
) where
|
||||
M: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, &mut dyn Iterator<Item = PhysicalPosition<f64>>),
|
||||
T: 'static
|
||||
C: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
FingerId,
|
||||
&mut dyn Iterator<Item = (PhysicalPosition<f64>, Force)>,
|
||||
&mut dyn Iterator<Item = (ModifiersState, PhysicalPosition<f64>, PointerSource)>,
|
||||
),
|
||||
B: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
PhysicalPosition<f64>,
|
||||
ButtonsState,
|
||||
MouseButton,
|
||||
ElementState,
|
||||
ButtonSource,
|
||||
),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
let canvas = canvas_common.raw().clone();
|
||||
self.on_cursor_move =
|
||||
Some(canvas_common.add_event("pointermove", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = DeviceId::new(pointer_id);
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
|
||||
// chorded button event
|
||||
if let Some(button) = event::mouse_button(&event) {
|
||||
|
|
@ -208,11 +187,34 @@ impl PointerHandler {
|
|||
let _ = canvas.focus();
|
||||
}
|
||||
|
||||
let state = if event::mouse_buttons(&event).contains(button.into()) {
|
||||
ElementState::Pressed
|
||||
} else {
|
||||
ElementState::Released
|
||||
};
|
||||
|
||||
let button = match kind {
|
||||
PointerKind::Mouse => ButtonSource::Mouse(button),
|
||||
PointerKind::Touch(finger_id) => {
|
||||
let button_id = button.to_id();
|
||||
|
||||
if button_id != 1 {
|
||||
tracing::error!("unexpected touch button id: {button_id}");
|
||||
}
|
||||
|
||||
ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
}
|
||||
},
|
||||
PointerKind::Unknown => todo!(),
|
||||
};
|
||||
|
||||
button_handler(
|
||||
modifiers,
|
||||
event::mouse_modifiers(&event),
|
||||
device_id,
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_buttons(&event),
|
||||
state,
|
||||
button,
|
||||
);
|
||||
|
||||
|
|
@ -221,44 +223,24 @@ impl PointerHandler {
|
|||
|
||||
// pointer move event
|
||||
let scale = super::scale_factor(&window);
|
||||
match event.pointer_type().as_str() {
|
||||
"touch" => touch_handler(
|
||||
modifiers,
|
||||
device_id,
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
&mut event::pointer_move_event(event).map(|event| {
|
||||
(
|
||||
event::mouse_position(&event).to_physical(scale),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
)
|
||||
}),
|
||||
),
|
||||
_ => mouse_handler(
|
||||
modifiers,
|
||||
device_id,
|
||||
&mut event::pointer_move_event(event)
|
||||
.map(|event| event::mouse_position(&event).to_physical(scale)),
|
||||
),
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_touch_cancel<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_touch_cancel =
|
||||
Some(canvas_common.add_event("pointercancel", move |event: PointerEvent| {
|
||||
if event.pointer_type() == "touch" {
|
||||
let pointer_id = event.pointer_id();
|
||||
handler(
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
}
|
||||
cursor_handler(
|
||||
device_id,
|
||||
&mut event::pointer_move_event(event).map(|event| {
|
||||
(
|
||||
event::mouse_modifiers(&event),
|
||||
event::mouse_position(&event).to_physical(scale),
|
||||
match kind {
|
||||
PointerKind::Mouse => PointerSource::Mouse,
|
||||
PointerKind::Touch(finger_id) => PointerSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
PointerKind::Unknown => PointerSource::Unknown,
|
||||
},
|
||||
)
|
||||
}),
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue