From 0122cf27ceb25804f3f20796509e3a0abadd20df Mon Sep 17 00:00:00 2001 From: Joonas Satka Date: Thu, 20 Jan 2022 23:03:37 +0200 Subject: [PATCH] Add touchpad rotate support for macOS --- CHANGELOG.md | 2 +- ...uchpad_magnify.rs => touchpad_gestures.rs} | 9 ++++- src/event.rs | 30 ++++++++++++++++ src/platform_impl/macos/view.rs | 35 +++++++++++++++++-- 4 files changed, 72 insertions(+), 4 deletions(-) rename examples/{touchpad_magnify.rs => touchpad_gestures.rs} (75%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4edcb1ca909..1862830e9c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Unreleased - **Breaking:** Rename the `Exit` variant of `ControlFlow` to `ExitWithCode`, which holds a value to control the exit code after running. Add an `Exit` constant which aliases to `ExitWithCode(0)` instead to avoid major breakage. This shouldn't affect most existing programs. -- On macOS, add support for touchpad magnification gesture with new event `WindowEvent::TouchpadMagnify`. +- On macOS, add support for touchpad magnification and rotation gestures with new events `WindowEvent::TouchpadMagnify` and `WindowEvent::TouchpadRotate`. # 0.26.1 (2022-01-05) diff --git a/examples/touchpad_magnify.rs b/examples/touchpad_gestures.rs similarity index 75% rename from examples/touchpad_magnify.rs rename to examples/touchpad_gestures.rs index 801b3ade30e..0086c4f49fa 100644 --- a/examples/touchpad_magnify.rs +++ b/examples/touchpad_gestures.rs @@ -10,7 +10,7 @@ fn main() { let event_loop = EventLoop::new(); let _window = WindowBuilder::new() - .with_title("Touchpad magnify events") + .with_title("Touchpad gestures") .build(&event_loop) .unwrap(); @@ -29,6 +29,13 @@ fn main() { println!("Zoomed out {}", delta); } }, + WindowEvent::TouchpadRotate { delta, .. } => { + if delta > 0.0 { + println!("Rotated left {}", delta); + } else { + println!("Rotated right {}", delta); + } + }, _ => (), }, _ => (), diff --git a/src/event.rs b/src/event.rs index eeb9a52a666..a19eb55ded0 100644 --- a/src/event.rs +++ b/src/event.rs @@ -318,6 +318,18 @@ pub enum WindowEvent<'a> { phase: TouchPhase, }, + /// Touchpad rotation event with two-finger rotation gesture. + /// + /// Positive delta values indicate rotation to left (counterclockwise) and + /// negative delta values indicate rotation to right (clockwise). + /// + /// At the moment, only supported on macOS. + TouchpadRotate { + device_id: DeviceId, + delta: f32, + phase: TouchPhase, + }, + /// Touchpad pressure event. /// /// At the moment, only supported on Apple forcetouch-capable macbooks. @@ -439,6 +451,15 @@ impl Clone for WindowEvent<'static> { delta: *delta, phase: *phase, }, + TouchpadRotate { + device_id, + delta, + phase + } => TouchpadRotate { + device_id: *device_id, + delta: *delta, + phase: *phase, + }, TouchpadPressure { device_id, pressure, @@ -534,6 +555,15 @@ impl<'a> WindowEvent<'a> { delta, phase, }), + TouchpadRotate { + device_id, + delta, + phase + } => Some(TouchpadRotate { + device_id, + delta, + phase, + }), TouchpadPressure { device_id, pressure, diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index 035981cb269..38ba634aa93 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -241,6 +241,10 @@ lazy_static! { sel!(magnifyWithEvent:), magnify_with_event as extern "C" fn(&Object, Sel, id), ); + decl.add_method( + sel!(rotateWithEvent:), + rotate_with_event as extern "C" fn(&Object, Sel, id), + ); decl.add_method( sel!(pressureChangeWithEvent:), pressure_change_with_event as extern "C" fn(&Object, Sel, id), @@ -1053,8 +1057,6 @@ extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) { extern "C" fn magnify_with_event(this: &Object, _sel: Sel, event: id) { trace!("Triggered `magnifyWithEvent`"); - mouse_motion(this, event); - unsafe { let state_ptr: *mut c_void = *this.get_ivar("winitState"); let state = &mut *(state_ptr as *mut ViewState); @@ -1081,6 +1083,35 @@ extern "C" fn magnify_with_event(this: &Object, _sel: Sel, event: id) { trace!("Completed `magnifyWithEvent`"); } +extern "C" fn rotate_with_event(this: &Object, _sel: Sel, event: id) { + trace!("Triggered `rotateWithEvent`"); + + unsafe { + let state_ptr: *mut c_void = *this.get_ivar("winitState"); + let state = &mut *(state_ptr as *mut ViewState); + + let delta = event.rotation(); + let phase = match event.phase() { + NSEventPhase::NSEventPhaseBegan => TouchPhase::Started, + NSEventPhase::NSEventPhaseChanged => TouchPhase::Moved, + NSEventPhase::NSEventPhaseEnded => TouchPhase::Ended, + _ => return + }; + + let window_event = Event::WindowEvent { + window_id: WindowId(get_window_id(state.ns_window)), + event: WindowEvent::TouchpadRotate { + device_id: DEVICE_ID, + delta, + phase, + }, + }; + + AppState::queue_event(EventWrapper::StaticEvent(window_event)); + } + trace!("Completed `rotateWithEvent`"); +} + extern "C" fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) { trace!("Triggered `pressureChangeWithEvent`");