Skip to content

Commit

Permalink
Add trackpad gesture PointerData types (flutter#28571)
Browse files Browse the repository at this point in the history
* Implement trackpad gestures in engine

* Remove the platform implementations

* Add new device type for trackpad

* Add back the necessary changes for Android

* Address feedback

* Fix doc typos
  • Loading branch information
moffatman authored Feb 10, 2022
1 parent fe08734 commit 2062e57
Show file tree
Hide file tree
Showing 13 changed files with 356 additions and 6 deletions.
8 changes: 7 additions & 1 deletion lib/ui/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ class PlatformDispatcher {
// * pointer_data.cc
// * pointer.dart
// * AndroidTouchProcessor.java
static const int _kPointerDataFieldCount = 29;
static const int _kPointerDataFieldCount = 35;

static PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
const int kStride = Int64List.bytesPerElement;
Expand Down Expand Up @@ -381,6 +381,12 @@ class PlatformDispatcher {
platformData: packet.getInt64(kStride * offset++, _kFakeHostEndian),
scrollDeltaX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
scrollDeltaY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
panX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
panY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
panDeltaX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
panDeltaY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
scale: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
rotation: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
));
assert(offset == (i + 1) * _kPointerDataFieldCount);
}
Expand Down
60 changes: 59 additions & 1 deletion lib/ui/pointer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ enum PointerChange {

/// The pointer has stopped making contact with the device.
up,

/// A pan/zoom has started on this pointer.
panZoomStart,

/// The pan/zoom on this pointer has updated.
panZoomUpdate,

/// The pan/zoom on this pointer has ended.
panZoomEnd,
}

/// The kind of pointer device.
Expand All @@ -52,6 +61,9 @@ enum PointerDeviceKind {
/// A pointer device with a stylus that has been inverted.
invertedStylus,

/// A touch-based pointer device with an indirect surface.
trackpad,

/// An unknown pointer device.
unknown
}
Expand Down Expand Up @@ -101,6 +113,12 @@ class PointerData {
this.platformData = 0,
this.scrollDeltaX = 0.0,
this.scrollDeltaY = 0.0,
this.panX = 0.0,
this.panY = 0.0,
this.panDeltaX = 0.0,
this.panDeltaY = 0.0,
this.scale = 0.0,
this.rotation = 0.0,
});

/// Unique identifier that ties the [PointerEvent] to embedder event created it.
Expand Down Expand Up @@ -265,6 +283,40 @@ class PointerData {
/// The amount to scroll in the y direction, in physical pixels.
final double scrollDeltaY;

/// For events with change of PointerChange.panZoomUpdate:
///
/// The current panning magnitude of the pan/zoom in the x direction, in
/// physical pixels.
final double panX;

/// For events with change of PointerChange.panZoomUpdate:
///
/// The current panning magnitude of the pan/zoom in the y direction, in
/// physical pixels.
final double panY;

/// For events with change of PointerChange.panZoomUpdate:
///
/// The difference in panning of the pan/zoom in the x direction since the
/// latest panZoomUpdate event, in physical pixels.
final double panDeltaX;

/// For events with change of PointerChange.panZoomUpdate:
///
/// The difference in panning of the pan/zoom in the y direction since the
/// last panZoomUpdate event, in physical pixels.
final double panDeltaY;

/// For events with change of PointerChange.panZoomUpdate:
///
/// The current scale of the pan/zoom (unitless), with 1.0 as the initial scale.
final double scale;

/// For events with change of PointerChange.panZoomUpdate:
///
/// The current angle of the pan/zoom in radians, with 0.0 as the initial angle.
final double rotation;

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

Expand Down Expand Up @@ -298,7 +350,13 @@ class PointerData {
'tilt: $tilt, '
'platformData: $platformData, '
'scrollDeltaX: $scrollDeltaX, '
'scrollDeltaY: $scrollDeltaY'
'scrollDeltaY: $scrollDeltaY, '
'panX: $panX, '
'panY: $panY, '
'panDeltaX: $panDeltaX, '
'panDeltaY: $panDeltaY, '
'scale: $scale, '
'rotation: $rotation'
')';
}
}
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 @@ -10,7 +10,7 @@
namespace flutter {

// If this value changes, update the pointer data unpacking code in hooks.dart.
static constexpr int kPointerDataFieldCount = 29;
static constexpr int kPointerDataFieldCount = 35;
static constexpr int kBytesPerField = sizeof(int64_t);
// Must match the button constants in events.dart.
enum PointerButtonMouse : int64_t {
Expand Down Expand Up @@ -42,6 +42,9 @@ struct alignas(8) PointerData {
kDown,
kMove,
kUp,
kPanZoomStart,
kPanZoomUpdate,
kPanZoomEnd,
};

// Must match the PointerDeviceKind enum in pointer.dart.
Expand All @@ -50,6 +53,7 @@ struct alignas(8) PointerData {
kMouse,
kStylus,
kInvertedStylus,
kTrackpad,
};

// Must match the PointerSignalKind enum in pointer.dart.
Expand Down Expand Up @@ -87,6 +91,12 @@ struct alignas(8) PointerData {
int64_t platformData;
double scroll_delta_x;
double scroll_delta_y;
double pan_x;
double pan_y;
double pan_delta_x;
double pan_delta_y;
double scale;
double rotation;

void Clear();
};
Expand Down
92 changes: 92 additions & 0 deletions lib/ui/window/pointer_data_packet_converter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "flutter/lib/ui/window/pointer_data_packet_converter.h"

#include <cmath>
#include <cstring>

#include "flutter/fml/logging.h"
Expand Down Expand Up @@ -207,6 +208,88 @@ void PointerDataPacketConverter::ConvertPointerData(
converted_pointers.push_back(pointer_data);
break;
}
case PointerData::Change::kPanZoomStart: {
// Makes sure we have an existing pointer
auto iter = states_.find(pointer_data.device);
PointerState state;
if (iter == states_.end()) {
// Synthesizes add event if the pointer is not previously added.
PointerData synthesized_add_event = pointer_data;
synthesized_add_event.change = PointerData::Change::kAdd;
synthesized_add_event.synthesized = 1;
synthesized_add_event.buttons = 0;
state = EnsurePointerState(synthesized_add_event);
converted_pointers.push_back(synthesized_add_event);
} else {
state = iter->second;
}
FML_DCHECK(!state.is_down);
FML_DCHECK(!state.is_pan_zoom_active);
if (LocationNeedsUpdate(pointer_data, state)) {
// Synthesizes a hover event if the location does not match.
PointerData synthesized_hover_event = pointer_data;
synthesized_hover_event.change = PointerData::Change::kHover;
synthesized_hover_event.synthesized = 1;
synthesized_hover_event.buttons = 0;

UpdateDeltaAndState(synthesized_hover_event, state);
converted_pointers.push_back(synthesized_hover_event);
}

UpdatePointerIdentifier(pointer_data, state, true);
state.is_pan_zoom_active = true;
state.pan_x = 0;
state.pan_y = 0;
state.scale = 1;
state.rotation = 0;
states_[pointer_data.device] = state;
converted_pointers.push_back(pointer_data);
break;
}
case PointerData::Change::kPanZoomUpdate: {
// Makes sure we have an existing pointer in pan_zoom_active state
auto iter = states_.find(pointer_data.device);
FML_DCHECK(iter != states_.end());
PointerState state = iter->second;
FML_DCHECK(!state.is_down);
FML_DCHECK(state.is_pan_zoom_active);

UpdatePointerIdentifier(pointer_data, state, false);
UpdateDeltaAndState(pointer_data, state);

converted_pointers.push_back(pointer_data);
break;
}
case PointerData::Change::kPanZoomEnd: {
// Makes sure we have an existing pointer in pan_zoom_active state
auto iter = states_.find(pointer_data.device);
FML_DCHECK(iter != states_.end());
PointerState state = iter->second;
FML_DCHECK(state.is_pan_zoom_active);

UpdatePointerIdentifier(pointer_data, state, false);

if (LocationNeedsUpdate(pointer_data, state)) {
// Synthesizes an update event if the location does not match.
PointerData synthesized_move_event = pointer_data;
synthesized_move_event.change = PointerData::Change::kPanZoomUpdate;
synthesized_move_event.pan_x = state.pan_x;
synthesized_move_event.pan_y = state.pan_y;
synthesized_move_event.pan_delta_x = 0;
synthesized_move_event.pan_delta_y = 0;
synthesized_move_event.scale = state.scale;
synthesized_move_event.rotation = state.rotation;
synthesized_move_event.synthesized = 1;

UpdateDeltaAndState(synthesized_move_event, state);
converted_pointers.push_back(synthesized_move_event);
}

state.is_pan_zoom_active = false;
states_[pointer_data.device] = state;
converted_pointers.push_back(pointer_data);
break;
}
default: {
converted_pointers.push_back(pointer_data);
break;
Expand Down Expand Up @@ -261,8 +344,11 @@ PointerState PointerDataPacketConverter::EnsurePointerState(
PointerState state;
state.pointer_identifier = 0;
state.is_down = false;
state.is_pan_zoom_active = false;
state.physical_x = pointer_data.physical_x;
state.physical_y = pointer_data.physical_y;
state.pan_x = 0;
state.pan_y = 0;
states_[pointer_data.device] = state;
return state;
}
Expand All @@ -271,8 +357,14 @@ void PointerDataPacketConverter::UpdateDeltaAndState(PointerData& pointer_data,
PointerState& state) {
pointer_data.physical_delta_x = pointer_data.physical_x - state.physical_x;
pointer_data.physical_delta_y = pointer_data.physical_y - state.physical_y;
pointer_data.pan_delta_x = pointer_data.pan_x - state.pan_x;
pointer_data.pan_delta_y = pointer_data.pan_y - state.pan_y;
state.physical_x = pointer_data.physical_x;
state.physical_y = pointer_data.physical_y;
state.pan_x = pointer_data.pan_x;
state.pan_y = pointer_data.pan_y;
state.scale = pointer_data.scale;
state.rotation = pointer_data.rotation;
states_[pointer_data.device] = state;
}

Expand Down
5 changes: 5 additions & 0 deletions lib/ui/window/pointer_data_packet_converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,13 @@ namespace flutter {
struct PointerState {
int64_t pointer_identifier;
bool is_down;
bool is_pan_zoom_active;
double physical_x;
double physical_y;
double pan_x;
double pan_y;
double scale;
double rotation;
int64_t buttons;
};

Expand Down
Loading

0 comments on commit 2062e57

Please sign in to comment.