-
Notifications
You must be signed in to change notification settings - Fork 6k
Add support for double tap action from Apple Pencil 2 #39267
Changes from 24 commits
a945890
04b8708
6b7061a
3818c77
1b6c8f5
9c31bd1
c2450d4
0317a34
61296be
2b5a6b9
c18f4e9
9f780ce
25f6607
2ec9688
a50f554
a27ba22
1cdf0ec
b348378
4e14bbf
c8a8cd7
69d1035
b162cbc
79b790f
912a4cc
1393fae
9527282
b09a991
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,7 +11,7 @@ namespace flutter { | |
|
|
||
| // If this value changes, update the pointer data unpacking code in | ||
| // platform_dispatcher.dart. | ||
| static constexpr int kPointerDataFieldCount = 35; | ||
| static constexpr int kPointerDataFieldCount = 36; | ||
| static constexpr int kBytesPerField = sizeof(int64_t); | ||
| // Must match the button constants in events.dart. | ||
| enum PointerButtonMouse : int64_t { | ||
|
|
@@ -63,6 +63,17 @@ struct alignas(8) PointerData { | |
| kScroll, | ||
| kScrollInertiaCancel, | ||
| kScale, | ||
| kStylusAuxiliaryAction, | ||
| }; | ||
|
|
||
| // Must match the PreferredStylusAuxiliaryAction enum in pointer.dart. | ||
|
|
||
|
||
| enum class PreferredStylusAuxiliaryAction : int64_t { | ||
| kIgnore, | ||
| kShowColorPalette, | ||
| kSwitchEraser, | ||
| kSwitchPrevious, | ||
| kUnknown | ||
| }; | ||
|
|
||
| int64_t embedder_id; | ||
|
|
@@ -100,6 +111,7 @@ struct alignas(8) PointerData { | |
| double pan_delta_y; | ||
| double scale; | ||
| double rotation; | ||
| PreferredStylusAuxiliaryAction preferred_auxiliary_stylus_action; | ||
|
|
||
| void Clear(); | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,18 +66,36 @@ public class AndroidTouchProcessor { | |
| PointerSignalKind.SCROLL, | ||
| PointerSignalKind.SCROLL_INERTIA_CANCEL, | ||
| PointerSignalKind.SCALE, | ||
| PointerSignalKind.STYLUS_AUXILIARY_ACTION, | ||
| PointerSignalKind.UNKNOWN | ||
| }) | ||
| public @interface PointerSignalKind { | ||
| int NONE = 0; | ||
| int SCROLL = 1; | ||
| int SCROLL_INERTIA_CANCEL = 2; | ||
| int SCALE = 3; | ||
| int STYLUS_AUXILIARY_ACTION = 3; | ||
| int SCALE = 4; | ||
|
||
| int UNKNOWN = 5; | ||
| } | ||
|
|
||
| // Must match the PointerPreferredStylusAuxiliaryAction enum in pointer.dart. | ||
| @IntDef({ | ||
| PointerPreferredStylusAuxiliaryAction.IGNORE, | ||
| PointerPreferredStylusAuxiliaryAction.SHOW_COLOR_PALETTE, | ||
| PointerPreferredStylusAuxiliaryAction.SWITCH_ERASER, | ||
| PointerPreferredStylusAuxiliaryAction.SWITCH_PREVIOUS, | ||
| PointerPreferredStylusAuxiliaryAction.UNKNOWN | ||
| }) | ||
| public @interface PointerPreferredStylusAuxiliaryAction { | ||
| int IGNORE = 0; | ||
| int SHOW_COLOR_PALETTE = 1; | ||
| int SWITCH_ERASER = 2; | ||
| int SWITCH_PREVIOUS = 3; | ||
| int UNKNOWN = 4; | ||
| } | ||
|
|
||
| // Must match the unpacking code in hooks.dart. | ||
| private static final int POINTER_DATA_FIELD_COUNT = 35; | ||
| private static final int POINTER_DATA_FIELD_COUNT = 36; | ||
| @VisibleForTesting static final int BYTES_PER_FIELD = 8; | ||
|
|
||
| // This value must match the value in framework's platform_view.dart. | ||
|
|
@@ -355,6 +373,8 @@ private void addPointerForIndex( | |
| packet.putDouble(1.0); // scale | ||
| packet.putDouble(0.0); // rotation | ||
|
|
||
| packet.putLong(PointerPreferredStylusAuxiliaryAction.IGNORE); // preferred stylus action | ||
|
|
||
| if (isTrackpadPan && getPointerChangeForPanZoom(pointerChange) == PointerChange.PAN_ZOOM_END) { | ||
| ongoingPans.remove(event.getPointerId(pointerIndex)); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -56,7 +56,9 @@ | |
| // This is left a FlutterBinaryMessenger privately for now to give people a chance to notice the | ||
| // change. Unfortunately unless you have Werror turned on, incompatible pointers as arguments are | ||
| // just a warning. | ||
| @interface FlutterViewController () <FlutterBinaryMessenger, UIScrollViewDelegate> | ||
| @interface FlutterViewController () <FlutterBinaryMessenger, | ||
| UIScrollViewDelegate, | ||
| UIPencilInteractionDelegate> | ||
| @property(nonatomic, readwrite, getter=isDisplayingFlutterUI) BOOL displayingFlutterUI; | ||
| @property(nonatomic, assign) BOOL isHomeIndicatorHidden; | ||
| @property(nonatomic, assign) BOOL isPresentingViewControllerAnimating; | ||
|
|
@@ -97,7 +99,7 @@ @interface FlutterViewController () <FlutterBinaryMessenger, UIScrollViewDelegat | |
| // Trackpad rotating | ||
| @property(nonatomic, retain) | ||
| UIRotationGestureRecognizer* rotationGestureRecognizer API_AVAILABLE(ios(13.4)); | ||
|
|
||
| @property(nonatomic, retain) UIPencilInteraction* pencilInteraction API_AVAILABLE(ios(13.4)); | ||
LouiseHsu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /** | ||
| * Creates and registers plugins used by this view controller. | ||
| */ | ||
|
|
@@ -718,6 +720,10 @@ - (void)viewDidLoad { | |
| [self createTouchRateCorrectionVSyncClientIfNeeded]; | ||
|
|
||
| if (@available(iOS 13.4, *)) { | ||
| _pencilInteraction = [[UIPencilInteraction alloc] init]; | ||
| _pencilInteraction.delegate = self; | ||
| [_flutterView addInteraction:_pencilInteraction]; | ||
|
|
||
| _hoverGestureRecognizer = | ||
| [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(hoverEvent:)]; | ||
| _hoverGestureRecognizer.delegate = self; | ||
|
|
@@ -891,6 +897,8 @@ - (void)dealloc { | |
| [_pinchGestureRecognizer release]; | ||
| _rotationGestureRecognizer.delegate = nil; | ||
| [_rotationGestureRecognizer release]; | ||
| _pencilInteraction.delegate = nil; | ||
| [_pencilInteraction release]; | ||
| [super dealloc]; | ||
| } | ||
|
|
||
|
|
@@ -965,7 +973,7 @@ - (void)goToApplicationLifecycle:(nonnull NSString*)state { | |
| case UITouchTypeDirect: | ||
| case UITouchTypeIndirect: | ||
| return flutter::PointerData::DeviceKind::kTouch; | ||
| case UITouchTypeStylus: | ||
| case UITouchTypePencil: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this change intended?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, UITouchTypeStylus is deprecated and is suggested https://developer.apple.com/documentation/uikit/uitouchtype/uitouchtypestylus |
||
| return flutter::PointerData::DeviceKind::kStylus; | ||
| case UITouchTypeIndirectPointer: | ||
| return flutter::PointerData::DeviceKind::kMouse; | ||
|
|
@@ -1220,6 +1228,50 @@ - (void)invalidateTouchRateCorrectionVSyncClient { | |
| _touchRateCorrectionVSyncClient = nil; | ||
| } | ||
|
|
||
| #pragma mark - Stylus Events | ||
|
|
||
| - (void)pencilInteractionDidTap:(UIPencilInteraction*)interaction API_AVAILABLE(ios(13.4)) { | ||
| flutter::PointerData pointer_data = [self createAuxillaryStylusActionData]; | ||
|
|
||
| auto packet = std::make_unique<flutter::PointerDataPacket>(1); | ||
| packet->SetPointerData(/*index=*/0, pointer_data); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can probably put this packet creation into the helper so that it's also unit tested. |
||
| [_engine.get() dispatchPointerDataPacket:std::move(packet)]; | ||
| } | ||
|
|
||
| - (flutter::PointerData)createAuxillaryStylusActionData API_AVAILABLE(ios(13.4)) { | ||
| flutter::PointerData pointer_data; | ||
| pointer_data.Clear(); | ||
|
|
||
| switch (UIPencilInteraction.preferredTapAction) { | ||
| case UIPencilPreferredActionIgnore: | ||
| pointer_data.preferred_auxiliary_stylus_action = | ||
| flutter::PointerData::PreferredStylusAuxiliaryAction::kIgnore; | ||
| break; | ||
| case UIPencilPreferredActionShowColorPalette: | ||
| pointer_data.preferred_auxiliary_stylus_action = | ||
| flutter::PointerData::PreferredStylusAuxiliaryAction::kShowColorPalette; | ||
| break; | ||
| case UIPencilPreferredActionSwitchEraser: | ||
| pointer_data.preferred_auxiliary_stylus_action = | ||
| flutter::PointerData::PreferredStylusAuxiliaryAction::kSwitchEraser; | ||
| break; | ||
| case UIPencilPreferredActionSwitchPrevious: | ||
| pointer_data.preferred_auxiliary_stylus_action = | ||
| flutter::PointerData::PreferredStylusAuxiliaryAction::kSwitchPrevious; | ||
| break; | ||
| default: | ||
| pointer_data.preferred_auxiliary_stylus_action = | ||
| flutter::PointerData::PreferredStylusAuxiliaryAction::kUnknown; | ||
| break; | ||
LouiseHsu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| pointer_data.time_stamp = [[NSProcessInfo processInfo] systemUptime] * kMicrosecondsPerSecond; | ||
| pointer_data.kind = flutter::PointerData::DeviceKind::kStylus; | ||
| pointer_data.signal_kind = flutter::PointerData::SignalKind::kStylusAuxiliaryAction; | ||
|
|
||
| return pointer_data; | ||
| } | ||
|
|
||
| #pragma mark - Handle view resizing | ||
|
|
||
| - (void)updateViewportMetrics { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just double check - did framework team already agree with using this naming?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its already in the design doc, and they didnt object - if they change their mind, I think it wouldnt be a big deal to change the naming.