mirror of
https://github.com/rust-windowing/winit.git
synced 2026-08-29 04:40:04 -04:00
Add Apple Pencil support on iOS (#4449)
With force, altitude, and azimuth data handling
This commit is contained in:
@@ -15,8 +15,8 @@ use objc2_ui_kit::{
|
|||||||
};
|
};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use winit_core::event::{
|
use winit_core::event::{
|
||||||
ButtonSource, ElementState, FingerId, Force, KeyEvent, PointerKind, PointerSource, TouchPhase,
|
ButtonSource, ElementState, FingerId, Force, KeyEvent, PointerKind, PointerSource,
|
||||||
WindowEvent,
|
TabletToolAngle, TabletToolButton, TabletToolData, TabletToolKind, TouchPhase, WindowEvent,
|
||||||
};
|
};
|
||||||
use winit_core::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKeyCode, PhysicalKey};
|
use winit_core::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKeyCode, PhysicalKey};
|
||||||
|
|
||||||
@@ -461,19 +461,18 @@ impl WinitView {
|
|||||||
let window = self.window().unwrap();
|
let window = self.window().unwrap();
|
||||||
let mut touch_events = Vec::new();
|
let mut touch_events = Vec::new();
|
||||||
for touch in touches {
|
for touch in touches {
|
||||||
if let UITouchType::Pencil = touch.r#type() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let logical_location = touch.locationInView(None);
|
let logical_location = touch.locationInView(None);
|
||||||
let touch_type = touch.r#type();
|
let touch_type = touch.r#type();
|
||||||
let force = if let UITouchType::Pencil = touch_type {
|
let force = if available!(ios = 9.0, tvos = 9.0, visionos = 1.0) {
|
||||||
None
|
let use_force = match touch_type {
|
||||||
} else if available!(ios = 9.0, tvos = 9.0, visionos = 1.0) {
|
UITouchType::Pencil => true,
|
||||||
let trait_collection = self.traitCollection();
|
_ => {
|
||||||
let touch_capability = trait_collection.forceTouchCapability();
|
let trait_collection = self.traitCollection();
|
||||||
// Both the OS _and_ the device need to be checked for force touch support.
|
trait_collection.forceTouchCapability() == UIForceTouchCapability::Available
|
||||||
if touch_capability == UIForceTouchCapability::Available {
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if use_force {
|
||||||
let force = touch.force();
|
let force = touch.force();
|
||||||
let max_possible_force = touch.maximumPossibleForce();
|
let max_possible_force = touch.maximumPossibleForce();
|
||||||
Some(Force::Calibrated {
|
Some(Force::Calibrated {
|
||||||
@@ -529,7 +528,7 @@ impl WinitView {
|
|||||||
primary,
|
primary,
|
||||||
position,
|
position,
|
||||||
kind: if let UITouchType::Pencil = touch_type {
|
kind: if let UITouchType::Pencil = touch_type {
|
||||||
PointerKind::Unknown
|
PointerKind::TabletTool(TabletToolKind::Pencil)
|
||||||
} else {
|
} else {
|
||||||
PointerKind::Touch(finger_id)
|
PointerKind::Touch(finger_id)
|
||||||
},
|
},
|
||||||
@@ -543,7 +542,12 @@ impl WinitView {
|
|||||||
state: ElementState::Pressed,
|
state: ElementState::Pressed,
|
||||||
position,
|
position,
|
||||||
button: if let UITouchType::Pencil = touch_type {
|
button: if let UITouchType::Pencil = touch_type {
|
||||||
ButtonSource::Unknown(0)
|
let tool_data = self.tablet_tool_data_for_pencil(&touch);
|
||||||
|
ButtonSource::TabletTool {
|
||||||
|
kind: TabletToolKind::Pencil,
|
||||||
|
button: TabletToolButton::Contact,
|
||||||
|
data: tool_data,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ButtonSource::Touch { finger_id, force }
|
ButtonSource::Touch { finger_id, force }
|
||||||
},
|
},
|
||||||
@@ -552,7 +556,11 @@ impl WinitView {
|
|||||||
},
|
},
|
||||||
UITouchPhase::Moved => {
|
UITouchPhase::Moved => {
|
||||||
let (primary, source) = if let UITouchType::Pencil = touch_type {
|
let (primary, source) = if let UITouchType::Pencil = touch_type {
|
||||||
(true, PointerSource::Unknown)
|
let tool_data = self.tablet_tool_data_for_pencil(&touch);
|
||||||
|
(true, PointerSource::TabletTool {
|
||||||
|
kind: TabletToolKind::Pencil,
|
||||||
|
data: tool_data,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
(ivars.primary_finger.get().unwrap() == finger_id, PointerSource::Touch {
|
(ivars.primary_finger.get().unwrap() == finger_id, PointerSource::Touch {
|
||||||
finger_id,
|
finger_id,
|
||||||
@@ -592,7 +600,12 @@ impl WinitView {
|
|||||||
state: ElementState::Released,
|
state: ElementState::Released,
|
||||||
position,
|
position,
|
||||||
button: if let UITouchType::Pencil = touch_type {
|
button: if let UITouchType::Pencil = touch_type {
|
||||||
ButtonSource::Unknown(0)
|
let tool_data = self.tablet_tool_data_for_pencil(&touch);
|
||||||
|
ButtonSource::TabletTool {
|
||||||
|
kind: TabletToolKind::Pencil,
|
||||||
|
button: TabletToolButton::Contact,
|
||||||
|
data: tool_data,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ButtonSource::Touch { finger_id, force }
|
ButtonSource::Touch { finger_id, force }
|
||||||
},
|
},
|
||||||
@@ -607,7 +620,7 @@ impl WinitView {
|
|||||||
primary,
|
primary,
|
||||||
position: Some(position),
|
position: Some(position),
|
||||||
kind: if let UITouchType::Pencil = touch_type {
|
kind: if let UITouchType::Pencil = touch_type {
|
||||||
PointerKind::Unknown
|
PointerKind::TabletTool(TabletToolKind::Pencil)
|
||||||
} else {
|
} else {
|
||||||
PointerKind::Touch(finger_id)
|
PointerKind::Touch(finger_id)
|
||||||
},
|
},
|
||||||
@@ -621,6 +634,32 @@ impl WinitView {
|
|||||||
app_state::handle_nonuser_events(mtm, touch_events);
|
app_state::handle_nonuser_events(mtm, touch_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tablet_tool_data_for_pencil(&self, touch: &UITouch) -> TabletToolData {
|
||||||
|
let force = if available!(ios = 9.0, tvos = 9.0, visionos = 1.0) {
|
||||||
|
let force_val = touch.force();
|
||||||
|
let max_force = touch.maximumPossibleForce();
|
||||||
|
Some(Force::Calibrated { force: force_val as _, max_possible_force: max_force as _ })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let angle = if available!(ios = 9.1, tvos = 9.0, visionos = 1.0) {
|
||||||
|
let altitude = touch.altitudeAngle();
|
||||||
|
let azimuth = touch.azimuthAngleInView(Some(self));
|
||||||
|
Some(TabletToolAngle { altitude: altitude as _, azimuth: azimuth as _ })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
TabletToolData {
|
||||||
|
force,
|
||||||
|
tangential_force: None, // iOS doesn't provide barrel pressure
|
||||||
|
twist: None, // iOS doesn't provide rotation/twist
|
||||||
|
tilt: None, // Will be calculated from angle if needed
|
||||||
|
angle,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_insert_text(&self, text: &NSString) {
|
fn handle_insert_text(&self, text: &NSString) {
|
||||||
let window = self.window().unwrap();
|
let window = self.window().unwrap();
|
||||||
let window_id = window.id();
|
let window_id = window.id();
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ changelog entry.
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Add `keyboard` support for OpenHarmony.
|
- Add `keyboard` support for OpenHarmony.
|
||||||
|
- On iOS, add Apple Pencil support with force, altitude, and azimuth data.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user