Skip to content

Commit

Permalink
Add touchpad magnify support for macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
jsatka committed Jan 20, 2022
1 parent 001fb7e commit bc3f998
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +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`.

# 0.26.1 (2022-01-05)

Expand Down
37 changes: 37 additions & 0 deletions examples/touchpad_magnify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};

fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();

let _window = WindowBuilder::new()
.with_title("Touchpad magnify events")
.build(&event_loop)
.unwrap();

println!("Only supported on macOS at the moment.");

event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;

match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::TouchpadMagnify { delta, .. } => {
if delta > 0.0 {
println!("Zoomed in {}", delta);
} else {
println!("Zoomed out {}", delta);
}
},
_ => (),
},
_ => (),
}
});
}
30 changes: 30 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,18 @@ pub enum WindowEvent<'a> {
modifiers: ModifiersState,
},

/// Touchpad magnification event with two-finger pinch gesture.
///
/// Positive delta values indicate magnification (zooming in) and
/// negative delta values indicate shrinking (zooming out).
///
/// At the moment, only supported on macOS.
TouchpadMagnify {
device_id: DeviceId,
delta: f64,
phase: TouchPhase,
},

/// Touchpad pressure event.
///
/// At the moment, only supported on Apple forcetouch-capable macbooks.
Expand Down Expand Up @@ -418,6 +430,15 @@ impl Clone for WindowEvent<'static> {
button: *button,
modifiers: *modifiers,
},
TouchpadMagnify {
device_id,
delta,
phase
} => TouchpadMagnify {
device_id: *device_id,
delta: *delta,
phase: *phase,
},
TouchpadPressure {
device_id,
pressure,
Expand Down Expand Up @@ -504,6 +525,15 @@ impl<'a> WindowEvent<'a> {
button,
modifiers,
}),
TouchpadMagnify {
device_id,
delta,
phase
} => Some(TouchpadMagnify {
device_id,
delta,
phase,
}),
TouchpadPressure {
device_id,
pressure,
Expand Down
35 changes: 35 additions & 0 deletions src/platform_impl/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ lazy_static! {
sel!(scrollWheel:),
scroll_wheel as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(magnifyWithEvent:),
magnify_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),
Expand Down Expand Up @@ -1046,6 +1050,37 @@ extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
trace!("Completed `scrollWheel`");
}

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);

let delta = event.magnification();
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::TouchpadMagnify {
device_id: DEVICE_ID,
delta,
phase,
},
};

AppState::queue_event(EventWrapper::StaticEvent(window_event));
}
trace!("Completed `magnifyWithEvent`");
}

extern "C" fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) {
trace!("Triggered `pressureChangeWithEvent`");

Expand Down

0 comments on commit bc3f998

Please sign in to comment.