Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/ui/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ class PlatformDispatcher {
// * pointer_data.cc
// * pointer.dart
// * AndroidTouchProcessor.java
static const int _kPointerDataFieldCount = 35;
static const int _kPointerDataFieldCount = 36;

static PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
const int kStride = Int64List.bytesPerElement;
Expand Down Expand Up @@ -417,6 +417,7 @@ class PlatformDispatcher {
panDeltaY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
scale: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
rotation: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
preferredAction: PointerPreferredAction.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not clear what "preferredAction" or PointerPreferredAction means in this context. How about preferredStylusAuxilliaryAction and PointerPreferredStylusAuxilliaryAction

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8790504096978029009/+/u/test:_Host_Tests_for_host_debug_unopt/stdout

�[0;32m[ RUN      ] �[mShellTest.CanCorrectlySynthesizePointerPacket
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: RangeError (index): Invalid value: Not in inclusive range 0..3: 1731047719413088311
#0      _Array.[] (dart:core-patch/array.dart:10:36)
#1      PlatformDispatcher._unpackPointerDataPacket (dart:ui/platform_dispatcher.dart:420:55)
#2      PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:364:9)
#3      _dispatchPointerDataPacket (dart:ui/hooks.dart:91:31)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its actually really confusing if both the actual event and the preferredAction are called PointerPreferredStylusAuxilliaryAction and PointerStylusAuxilliaryAction respectively, I got confused just now between the two as Im trying to change the names because then the only difference them is the "preferred", and its pretty verbose

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about StylusSecondaryGesture (double tap) + ConfiguredStylusAction (the preferred action)?

));
assert(offset == (i + 1) * _kPointerDataFieldCount);
}
Expand Down
18 changes: 18 additions & 0 deletions lib/ui/pointer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,21 @@ enum PointerSignalKind {
/// A pointer-generated scale event (e.g. trackpad pinch).
scale,

/// A stylus generated action (e.g. double tap on Apple Pencil 2)
stylusAction,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment on the naming here.


/// An unknown pointer signal kind.
unknown
}

/// The preferred action for stylus action
enum PointerPreferredAction {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this specify stylus then?

Suggested change
enum PointerPreferredAction {
enum PointerPreferredStylusAction {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hellohuanlin suggested preferredStylusAuxilliaryAction or PointerPreferredStylusAuxilliaryAction, what do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you have an extra "l" in "Auxiliary". But what does "Auxiliary" mean in this context?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I view stylus touching on screen as the "primary action" and Apple Pencil double tap as "auxiliary action". If we just call it "stylus action" or "pointer action", it sounds like stylus touching on screen (rather finger tapping on pencil in our case)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be a good question for the framework team, I'm sure they have prior art for this problem.

ignore,
showColorPalette,
switchEraser,
switchPrevious
Comment thread
LouiseHsu marked this conversation as resolved.
Outdated
}

/// Information about the state of a pointer.
class PointerData {
/// Creates an object that represents the state of a pointer.
Expand Down Expand Up @@ -176,6 +187,7 @@ class PointerData {
this.panDeltaY = 0.0,
this.scale = 0.0,
this.rotation = 0.0,
this.preferredAction = PointerPreferredAction.ignore,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning: lib/ui/ui.dart PointerData.Unnamed Constructor has a different parameter length than in lib/web_ui/ui.dart.

https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8790504096880865457/+/u/analyze_dart_ui/stdout

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path "lib/web_ui/ui.dart" doesnt exist, but I think this is because I need to update pointer packet on the Android side too

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One is udner flutter/lib/ui/pointer.dart, another one is under flutter/lib/web_ui/pointer.dart

});

/// Unique identifier that ties the [PointerEvent] to embedder event created it.
Expand Down Expand Up @@ -374,6 +386,11 @@ class PointerData {
/// The current angle of the pan/zoom in radians, with 0.0 as the initial angle.
final double rotation;

/// For events with signal kind of stylusAction
///
/// The current preferred action for stylusAction, with ignore as the default.
final PointerPreferredAction preferredAction;

@override
String toString() => 'PointerData(x: $physicalX, y: $physicalY)';

Expand Down Expand Up @@ -414,6 +431,7 @@ class PointerData {
'panDeltaY: $panDeltaY, '
'scale: $scale, '
'rotation: $rotation'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'rotation: $rotation'
'rotation: $rotation, '

'preferredAction: $preferredAction, '
')';
}
}
Expand Down
12 changes: 11 additions & 1 deletion lib/ui/window/pointer_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -63,6 +63,15 @@ struct alignas(8) PointerData {
kScroll,
kScrollInertiaCancel,
kScale,
kStylusAction,
};

// Must match the PointerPreferredAction enum in pointer.dart.
enum class PreferredAction : int64_t {
kIgnore,
kShowColorPalette,
kSwitchEraser,
kSwitchPrevious
};

int64_t embedder_id;
Expand Down Expand Up @@ -100,6 +109,7 @@ struct alignas(8) PointerData {
double pan_delta_y;
double scale;
double rotation;
PreferredAction preferred_action;

void Clear();
};
Expand Down
1 change: 1 addition & 0 deletions lib/ui/window/pointer_data_packet_converter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ void PointerDataPacketConverter::ConvertPointerData(
switch (pointer_data.signal_kind) {
case PointerData::SignalKind::kScroll:
case PointerData::SignalKind::kScrollInertiaCancel:
case PointerData::SignalKind::kStylusAction:
case PointerData::SignalKind::kScale: {
// Makes sure we have an existing pointer
auto iter = states_.find(pointer_data.device);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,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;
Expand Down Expand Up @@ -93,7 +95,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));
Comment thread
LouiseHsu marked this conversation as resolved.
/**
* Creates and registers plugins used by this view controller.
*/
Expand Down Expand Up @@ -709,6 +711,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;
Expand Down Expand Up @@ -956,7 +962,7 @@ - (void)goToApplicationLifecycle:(nonnull NSString*)state {
case UITouchTypeDirect:
case UITouchTypeIndirect:
return flutter::PointerData::DeviceKind::kTouch;
case UITouchTypeStylus:
case UITouchTypePencil:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this change intended?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The 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;
Expand Down Expand Up @@ -1211,6 +1217,40 @@ - (void)invalidateTouchRateCorrectionVSyncClient {
_touchRateCorrectionVSyncClient = nil;
}

#pragma mark - Stylus Events

#pragma clang diagnostic push

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this pragma push pop here for something? Can it be removed?


- (void)pencilInteractionDidTap:(UIPencilInteraction*)interaction API_AVAILABLE(ios(13.4)) {
flutter::PointerData pointer_data = [self generatePointerDataAtLastMouseLocation];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need the mouse location for this pointer_data?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this is not resolved - we don't need the mouse location here. Can probably just do

  flutter::PointerData pointer_data;
  pointer_data.Clear();


switch (UIPencilInteraction.preferredTapAction) {
case UIPencilPreferredActionIgnore:
pointer_data.preferred_action = flutter::PointerData::PreferredAction::kIgnore;
break;
case UIPencilPreferredActionShowColorPalette:
pointer_data.preferred_action = flutter::PointerData::PreferredAction::kShowColorPalette;
break;
case UIPencilPreferredActionSwitchEraser:
pointer_data.preferred_action = flutter::PointerData::PreferredAction::kSwitchEraser;
break;
case UIPencilPreferredActionSwitchPrevious:
pointer_data.preferred_action = flutter::PointerData::PreferredAction::kSwitchPrevious;
default:
break;
Comment thread
LouiseHsu marked this conversation as resolved.
}

pointer_data.device = reinterpret_cast<int64_t>(_pencilInteraction);
pointer_data.kind = flutter::PointerData::DeviceKind::kStylus;
pointer_data.signal_kind = flutter::PointerData::SignalKind::kStylusAction;

auto packet = std::make_unique<flutter::PointerDataPacket>(1);
packet->SetPointerData(/*index=*/0, pointer_data);
[_engine.get() dispatchPointerDataPacket:std::move(packet)];
}

#pragma clang diagnostic pop

#pragma mark - Handle view resizing

- (void)updateViewportMetrics {
Expand Down Expand Up @@ -1680,7 +1720,7 @@ - (void)pressesCancelled:(NSSet<UIPress*>*)presses

#pragma mark - Orientation updates

- (void)onOrientationPreferencesUpdated:(NSNotification*)notification {
- (void)onOrientationPreferencesUpdated:(NSNotification*)notification API_AVAILABLE(ios(12.1)) {
Comment thread
LouiseHsu marked this conversation as resolved.
Outdated
// Notifications may not be on the iOS UI thread
dispatch_async(dispatch_get_main_queue(), ^{
NSDictionary* info = notification.userInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ - (void)performOrientationUpdate:(UIInterfaceOrientationMask)new_preferences;
- (void)handlePressEvent:(FlutterUIPressProxy*)press
nextAction:(void (^)())next API_AVAILABLE(ios(13.4));
- (void)discreteScrollEvent:(UIPanGestureRecognizer*)recognizer;
- (void)pencilInteractionDidTap:(UIPencilInteraction*)interaction;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interface can implement the delegate protocol instead:

@interface FlutterViewController (Tests) <UIPencilInteractionDelegate>
Suggested change
- (void)pencilInteractionDidTap:(UIPencilInteraction*)interaction;

- (void)updateViewportMetrics;
- (void)onUserSettingsChanged:(NSNotification*)notification;
- (void)applicationWillTerminate:(NSNotification*)notification;
Expand Down Expand Up @@ -1479,6 +1480,27 @@ - (void)testMouseSupport API_AVAILABLE(ios(13.4)) {
dispatchPointerDataPacket:std::make_unique<flutter::PointerDataPacket>(0)];
}

- (void)testPencilSupport API_AVAILABLE(ios(13.4)) {
if (@available(iOS 13.4, *)) {
// noop
} else {
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need this with the API_AVAILABLE in the method signature.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section is in every other test in this file too, they also all have the API_AVAILABLE in the signature. should I remove it for the others too?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would be great, assuming they all pass. Thank you!


FlutterViewController* vc = [[FlutterViewController alloc] initWithEngine:self.mockEngine
nibName:nil
bundle:nil];
XCTAssertNotNil(vc);

id mockPencilInteraction = OCMClassMock([UIPencilInteraction class]);
XCTAssertNotNil(mockPencilInteraction);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to assert that the mock you just made isn't nil, then you're just testing that OCMock works.


[vc pencilInteractionDidTap:mockPencilInteraction];

[[[self.mockEngine verify] ignoringNonObjectArgs]
dispatchPointerDataPacket:std::make_unique<flutter::PointerDataPacket>(0)];
Comment thread
LouiseHsu marked this conversation as resolved.
Outdated
}

- (void)testFakeEventTimeStamp {
FlutterViewController* vc = [[FlutterViewController alloc] initWithEngine:self.mockEngine
nibName:nil
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2019,6 +2019,8 @@ inline flutter::PointerData::SignalKind ToPointerDataSignalKind(
return flutter::PointerData::SignalKind::kScrollInertiaCancel;
case kFlutterPointerSignalKindScale:
return flutter::PointerData::SignalKind::kScale;
case kFlutterPointerSignalKindStylusAction:
return flutter::PointerData::SignalKind::kStylusAction;
}
return flutter::PointerData::SignalKind::kNone;
}
Expand Down
1 change: 1 addition & 0 deletions shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,7 @@ typedef enum {
kFlutterPointerSignalKindScroll,
kFlutterPointerSignalKindScrollInertiaCancel,
kFlutterPointerSignalKindScale,
kFlutterPointerSignalKindStylusAction,
} FlutterPointerSignalKind;

typedef struct {
Expand Down