Skip to content

Commit b3c7635

Browse files
authored
Add Apple Pencil support on iOS (#4449)
With force, altitude, and azimuth data handling
1 parent 4aac778 commit b3c7635

File tree

2 files changed

+58
-18
lines changed

2 files changed

+58
-18
lines changed

winit-uikit/src/view.rs

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use objc2_ui_kit::{
1515
};
1616
use tracing::debug;
1717
use winit_core::event::{
18-
ButtonSource, ElementState, FingerId, Force, KeyEvent, PointerKind, PointerSource, TouchPhase,
19-
WindowEvent,
18+
ButtonSource, ElementState, FingerId, Force, KeyEvent, PointerKind, PointerSource,
19+
TabletToolAngle, TabletToolButton, TabletToolData, TabletToolKind, TouchPhase, WindowEvent,
2020
};
2121
use winit_core::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKeyCode, PhysicalKey};
2222

@@ -461,19 +461,18 @@ impl WinitView {
461461
let window = self.window().unwrap();
462462
let mut touch_events = Vec::new();
463463
for touch in touches {
464-
if let UITouchType::Pencil = touch.r#type() {
465-
continue;
466-
}
467-
468464
let logical_location = touch.locationInView(None);
469465
let touch_type = touch.r#type();
470-
let force = if let UITouchType::Pencil = touch_type {
471-
None
472-
} else if available!(ios = 9.0, tvos = 9.0, visionos = 1.0) {
473-
let trait_collection = self.traitCollection();
474-
let touch_capability = trait_collection.forceTouchCapability();
475-
// Both the OS _and_ the device need to be checked for force touch support.
476-
if touch_capability == UIForceTouchCapability::Available {
466+
let force = if available!(ios = 9.0, tvos = 9.0, visionos = 1.0) {
467+
let use_force = match touch_type {
468+
UITouchType::Pencil => true,
469+
_ => {
470+
let trait_collection = self.traitCollection();
471+
trait_collection.forceTouchCapability() == UIForceTouchCapability::Available
472+
},
473+
};
474+
475+
if use_force {
477476
let force = touch.force();
478477
let max_possible_force = touch.maximumPossibleForce();
479478
Some(Force::Calibrated {
@@ -529,7 +528,7 @@ impl WinitView {
529528
primary,
530529
position,
531530
kind: if let UITouchType::Pencil = touch_type {
532-
PointerKind::Unknown
531+
PointerKind::TabletTool(TabletToolKind::Pencil)
533532
} else {
534533
PointerKind::Touch(finger_id)
535534
},
@@ -543,7 +542,12 @@ impl WinitView {
543542
state: ElementState::Pressed,
544543
position,
545544
button: if let UITouchType::Pencil = touch_type {
546-
ButtonSource::Unknown(0)
545+
let tool_data = self.tablet_tool_data_for_pencil(&touch);
546+
ButtonSource::TabletTool {
547+
kind: TabletToolKind::Pencil,
548+
button: TabletToolButton::Contact,
549+
data: tool_data,
550+
}
547551
} else {
548552
ButtonSource::Touch { finger_id, force }
549553
},
@@ -552,7 +556,11 @@ impl WinitView {
552556
},
553557
UITouchPhase::Moved => {
554558
let (primary, source) = if let UITouchType::Pencil = touch_type {
555-
(true, PointerSource::Unknown)
559+
let tool_data = self.tablet_tool_data_for_pencil(&touch);
560+
(true, PointerSource::TabletTool {
561+
kind: TabletToolKind::Pencil,
562+
data: tool_data,
563+
})
556564
} else {
557565
(ivars.primary_finger.get().unwrap() == finger_id, PointerSource::Touch {
558566
finger_id,
@@ -592,7 +600,12 @@ impl WinitView {
592600
state: ElementState::Released,
593601
position,
594602
button: if let UITouchType::Pencil = touch_type {
595-
ButtonSource::Unknown(0)
603+
let tool_data = self.tablet_tool_data_for_pencil(&touch);
604+
ButtonSource::TabletTool {
605+
kind: TabletToolKind::Pencil,
606+
button: TabletToolButton::Contact,
607+
data: tool_data,
608+
}
596609
} else {
597610
ButtonSource::Touch { finger_id, force }
598611
},
@@ -607,7 +620,7 @@ impl WinitView {
607620
primary,
608621
position: Some(position),
609622
kind: if let UITouchType::Pencil = touch_type {
610-
PointerKind::Unknown
623+
PointerKind::TabletTool(TabletToolKind::Pencil)
611624
} else {
612625
PointerKind::Touch(finger_id)
613626
},
@@ -621,6 +634,32 @@ impl WinitView {
621634
app_state::handle_nonuser_events(mtm, touch_events);
622635
}
623636

637+
fn tablet_tool_data_for_pencil(&self, touch: &UITouch) -> TabletToolData {
638+
let force = if available!(ios = 9.0, tvos = 9.0, visionos = 1.0) {
639+
let force_val = touch.force();
640+
let max_force = touch.maximumPossibleForce();
641+
Some(Force::Calibrated { force: force_val as _, max_possible_force: max_force as _ })
642+
} else {
643+
None
644+
};
645+
646+
let angle = if available!(ios = 9.1, tvos = 9.0, visionos = 1.0) {
647+
let altitude = touch.altitudeAngle();
648+
let azimuth = touch.azimuthAngleInView(Some(self));
649+
Some(TabletToolAngle { altitude: altitude as _, azimuth: azimuth as _ })
650+
} else {
651+
None
652+
};
653+
654+
TabletToolData {
655+
force,
656+
tangential_force: None, // iOS doesn't provide barrel pressure
657+
twist: None, // iOS doesn't provide rotation/twist
658+
tilt: None, // Will be calculated from angle if needed
659+
angle,
660+
}
661+
}
662+
624663
fn handle_insert_text(&self, text: &NSString) {
625664
let window = self.window().unwrap();
626665
let window_id = window.id();

winit/src/changelog/unreleased.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ changelog entry.
4343
### Added
4444

4545
- Add `keyboard` support for OpenHarmony.
46+
- On iOS, add Apple Pencil support with force, altitude, and azimuth data.
4647

4748
### Changed
4849

0 commit comments

Comments
 (0)