diff --git a/CHANGELOG.md b/CHANGELOG.md index 577ef59a..fad7afd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - On Android, unimplemented events are marked as unhandled on the native event loop. - On Windows, added `WindowBuilderExtWindows::with_menu` to set a custom menu at window creation time. - On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. +- On Web, added support for `DeviceEvent::MouseMotion` to listen for relative mouse movements. # 0.24.0 (2020-12-09) diff --git a/src/platform_impl/web/event_loop/window_target.rs b/src/platform_impl/web/event_loop/window_target.rs index 7818ac0d..367556a7 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -1,6 +1,8 @@ use super::{super::monitor, backend, device, proxy::Proxy, runner, window}; use crate::dpi::{PhysicalSize, Size}; -use crate::event::{DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent}; +use crate::event::{ + DeviceEvent, DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent, +}; use crate::event_loop::ControlFlow; use crate::monitor::MonitorHandle as RootMH; use crate::window::{Theme, WindowId}; @@ -130,7 +132,7 @@ impl WindowTarget { }); let runner = self.runner.clone(); - canvas.on_cursor_move(move |pointer_id, position, modifiers| { + canvas.on_cursor_move(move |pointer_id, position, delta, modifiers| { runner.send_event(Event::WindowEvent { window_id: WindowId(id), event: WindowEvent::CursorMoved { @@ -139,6 +141,12 @@ impl WindowTarget { modifiers, }, }); + runner.send_event(Event::DeviceEvent { + device_id: DeviceId(device::Id(pointer_id)), + event: DeviceEvent::MouseMotion { + delta: (delta.x, delta.y), + }, + }); }); let runner = self.runner.clone(); diff --git a/src/platform_impl/web/stdweb/canvas.rs b/src/platform_impl/web/stdweb/canvas.rs index c68ec911..5bc8991f 100644 --- a/src/platform_impl/web/stdweb/canvas.rs +++ b/src/platform_impl/web/stdweb/canvas.rs @@ -222,13 +222,14 @@ impl Canvas { pub fn on_cursor_move(&mut self, mut handler: F) where - F: 'static + FnMut(i32, PhysicalPosition, ModifiersState), + F: 'static + FnMut(i32, PhysicalPosition, PhysicalPosition, ModifiersState), { // todo self.on_cursor_move = Some(self.add_event(move |event: PointerMoveEvent| { handler( event.pointer_id(), event::mouse_position(&event).to_physical(super::scale_factor()), + event::mouse_delta(&event).to_physical(super::scale_factor()), event::mouse_modifiers(&event), ); })); diff --git a/src/platform_impl/web/stdweb/event.rs b/src/platform_impl/web/stdweb/event.rs index d04298af..b4edcb72 100644 --- a/src/platform_impl/web/stdweb/event.rs +++ b/src/platform_impl/web/stdweb/event.rs @@ -30,6 +30,13 @@ pub fn mouse_position(event: &impl IMouseEvent) -> LogicalPosition { } } +pub fn mouse_delta(event: &impl IMouseEvent) -> LogicalPosition { + LogicalPosition { + x: event.movement_x() as f64, + y: event.movement_y() as f64, + } +} + pub fn mouse_scroll_delta(event: &MouseWheelEvent) -> Option { let x = event.delta_x(); let y = -event.delta_y(); diff --git a/src/platform_impl/web/web_sys/canvas.rs b/src/platform_impl/web/web_sys/canvas.rs index ae2fe0e1..8013e7b1 100644 --- a/src/platform_impl/web/web_sys/canvas.rs +++ b/src/platform_impl/web/web_sys/canvas.rs @@ -238,7 +238,7 @@ impl Canvas { pub fn on_cursor_move(&mut self, handler: F) where - F: 'static + FnMut(i32, PhysicalPosition, ModifiersState), + F: 'static + FnMut(i32, PhysicalPosition, PhysicalPosition, ModifiersState), { match &mut self.mouse_state { MouseState::HasPointerEvent(h) => h.on_cursor_move(&self.common, handler), diff --git a/src/platform_impl/web/web_sys/canvas/mouse_handler.rs b/src/platform_impl/web/web_sys/canvas/mouse_handler.rs index fcfb88b9..65450980 100644 --- a/src/platform_impl/web/web_sys/canvas/mouse_handler.rs +++ b/src/platform_impl/web/web_sys/canvas/mouse_handler.rs @@ -160,7 +160,7 @@ impl MouseHandler { pub fn on_cursor_move(&mut self, canvas_common: &super::Common, mut handler: F) where - F: 'static + FnMut(i32, PhysicalPosition, ModifiersState), + F: 'static + FnMut(i32, PhysicalPosition, PhysicalPosition, ModifiersState), { let mouse_capture_state = self.mouse_capture_state.clone(); let canvas = canvas_common.raw.clone(); @@ -190,9 +190,11 @@ impl MouseHandler { // use `offsetX`/`offsetY`. event::mouse_position_by_client(&event, &canvas) }; + let mouse_delta = event::mouse_delta(&event); handler( 0, mouse_pos.to_physical(super::super::scale_factor()), + mouse_delta.to_physical(super::super::scale_factor()), event::mouse_modifiers(&event), ); } diff --git a/src/platform_impl/web/web_sys/canvas/pointer_handler.rs b/src/platform_impl/web/web_sys/canvas/pointer_handler.rs index 4764e03c..046732f7 100644 --- a/src/platform_impl/web/web_sys/canvas/pointer_handler.rs +++ b/src/platform_impl/web/web_sys/canvas/pointer_handler.rs @@ -87,7 +87,7 @@ impl PointerHandler { pub fn on_cursor_move(&mut self, canvas_common: &super::Common, mut handler: F) where - F: 'static + FnMut(i32, PhysicalPosition, ModifiersState), + F: 'static + FnMut(i32, PhysicalPosition, PhysicalPosition, ModifiersState), { self.on_cursor_move = Some(canvas_common.add_event( "pointermove", @@ -95,6 +95,7 @@ impl PointerHandler { handler( event.pointer_id(), event::mouse_position(&event).to_physical(super::super::scale_factor()), + event::mouse_delta(&event).to_physical(super::super::scale_factor()), event::mouse_modifiers(&event), ); }, diff --git a/src/platform_impl/web/web_sys/event.rs b/src/platform_impl/web/web_sys/event.rs index 3d2b77b1..fb6c52d3 100644 --- a/src/platform_impl/web/web_sys/event.rs +++ b/src/platform_impl/web/web_sys/event.rs @@ -29,6 +29,13 @@ pub fn mouse_position(event: &MouseEvent) -> LogicalPosition { } } +pub fn mouse_delta(event: &MouseEvent) -> LogicalPosition { + LogicalPosition { + x: event.movement_x() as f64, + y: event.movement_y() as f64, + } +} + pub fn mouse_position_by_client( event: &MouseEvent, canvas: &HtmlCanvasElement,