Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 3bccd0a

Browse files
committed
Implement trackpad gestures in engine
1 parent 685c0a9 commit 3bccd0a

38 files changed

+1677
-118
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,9 @@ FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plu
17321732
FILE: ../../../flutter/shell/platform/windows/client_wrapper/plugin_registrar_windows_unittests.cc
17331733
FILE: ../../../flutter/shell/platform/windows/cursor_handler.cc
17341734
FILE: ../../../flutter/shell/platform/windows/cursor_handler.h
1735+
FILE: ../../../flutter/shell/platform/windows/direct_manipulation.cc
1736+
FILE: ../../../flutter/shell/platform/windows/direct_manipulation.h
1737+
FILE: ../../../flutter/shell/platform/windows/direct_manipulation_unittests.cc
17351738
FILE: ../../../flutter/shell/platform/windows/display_helper_winuwp.cc
17361739
FILE: ../../../flutter/shell/platform/windows/display_helper_winuwp.h
17371740
FILE: ../../../flutter/shell/platform/windows/dpi_utils_win32.cc

lib/ui/platform_dispatcher.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ class PlatformDispatcher {
341341
// * pointer_data.cc
342342
// * pointer.dart
343343
// * AndroidTouchProcessor.java
344-
static const int _kPointerDataFieldCount = 29;
344+
static const int _kPointerDataFieldCount = 35;
345345

346346
static PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
347347
const int kStride = Int64List.bytesPerElement;
@@ -381,6 +381,12 @@ class PlatformDispatcher {
381381
platformData: packet.getInt64(kStride * offset++, _kFakeHostEndian),
382382
scrollDeltaX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
383383
scrollDeltaY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
384+
panX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
385+
panY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
386+
panDeltaX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
387+
panDeltaY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
388+
scale: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
389+
rotation: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
384390
));
385391
assert(offset == (i + 1) * _kPointerDataFieldCount);
386392
}

lib/ui/pointer.dart

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ enum PointerChange {
3636

3737
/// The pointer has stopped making contact with the device.
3838
up,
39+
40+
/// A pan/zoom has started on this pointer
41+
panZoomStart,
42+
43+
/// The pan/zoom on this pointer has updated
44+
panZoomUpdate,
45+
46+
/// The pan/zoom on this pointer has ended
47+
panZoomEnd,
3948
}
4049

4150
/// The kind of pointer device.
@@ -101,6 +110,12 @@ class PointerData {
101110
this.platformData = 0,
102111
this.scrollDeltaX = 0.0,
103112
this.scrollDeltaY = 0.0,
113+
this.panX = 0.0,
114+
this.panY = 0.0,
115+
this.panDeltaX = 0.0,
116+
this.panDeltaY = 0.0,
117+
this.scale = 0.0,
118+
this.rotation = 0.0,
104119
});
105120

106121
/// Unique identifier that ties the [PointerEvent] to embedder event created it.
@@ -265,6 +280,36 @@ class PointerData {
265280
/// The amount to scroll in the y direction, in physical pixels.
266281
final double scrollDeltaY;
267282

283+
/// For events with change of PointerChange.panZoomUpdate:
284+
///
285+
/// The current panning magnitude of the pan/zoom in the x direction, in physical pixels.
286+
final double panX;
287+
288+
/// For events with change of PointerChange.panZoomUpdate:
289+
///
290+
/// The current panning magnitude of the pan/zoom in the x direction, in physical pixels.
291+
final double panY;
292+
293+
/// For events with change of PointerChange.panZoomUpdate:
294+
///
295+
/// The difference in panning of the pan/zoom in the x direction since the latest panZoomUpdate event, in physical pixels.
296+
final double panDeltaX;
297+
298+
/// For events with change of PointerChange.panZoomUpdate:
299+
///
300+
/// The difference in panning of the pan/zoom in the y direction since the last panZoomUpdate event, in physical pixels.
301+
final double panDeltaY;
302+
303+
/// For events with change of PointerChange.panZoomUpdate:
304+
///
305+
/// The current scale of the pan/zoom (unitless), with 1.0 as the initial scale.
306+
final double scale;
307+
308+
/// For events with change of PointerChange.panZoomUpdate:
309+
///
310+
/// The current angle of the pan/zoom in radians, with 0.0 as the initial angle.
311+
final double rotation;
312+
268313
@override
269314
String toString() => 'PointerData(x: $physicalX, y: $physicalY)';
270315

@@ -298,7 +343,13 @@ class PointerData {
298343
'tilt: $tilt, '
299344
'platformData: $platformData, '
300345
'scrollDeltaX: $scrollDeltaX, '
301-
'scrollDeltaY: $scrollDeltaY'
346+
'scrollDeltaY: $scrollDeltaY, '
347+
'panX: $panX, '
348+
'panY: $panY, '
349+
'panDeltaX: $panDeltaX, '
350+
'panDeltaY: $panDeltaY, '
351+
'scale: $scale, '
352+
'rotation: $rotation'
302353
')';
303354
}
304355
}

lib/ui/window/pointer_data.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
namespace flutter {
1111

1212
// If this value changes, update the pointer data unpacking code in hooks.dart.
13-
static constexpr int kPointerDataFieldCount = 29;
13+
static constexpr int kPointerDataFieldCount = 35;
1414
static constexpr int kBytesPerField = sizeof(int64_t);
1515
// Must match the button constants in events.dart.
1616
enum PointerButtonMouse : int64_t {
@@ -42,6 +42,9 @@ struct alignas(8) PointerData {
4242
kDown,
4343
kMove,
4444
kUp,
45+
kPanZoomStart,
46+
kPanZoomUpdate,
47+
kPanZoomEnd,
4548
};
4649

4750
// Must match the PointerDeviceKind enum in pointer.dart.
@@ -53,10 +56,7 @@ struct alignas(8) PointerData {
5356
};
5457

5558
// Must match the PointerSignalKind enum in pointer.dart.
56-
enum class SignalKind : int64_t {
57-
kNone,
58-
kScroll,
59-
};
59+
enum class SignalKind : int64_t { kNone, kScroll };
6060

6161
int64_t embedder_id;
6262
int64_t time_stamp;
@@ -87,6 +87,12 @@ struct alignas(8) PointerData {
8787
int64_t platformData;
8888
double scroll_delta_x;
8989
double scroll_delta_y;
90+
double pan_x;
91+
double pan_y;
92+
double pan_delta_x;
93+
double pan_delta_y;
94+
double scale;
95+
double rotation;
9096

9197
void Clear();
9298
};

lib/ui/window/pointer_data_packet_converter.cc

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

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

7+
#include <cmath>
78
#include <cstring>
89

910
#include "flutter/fml/logging.h"
@@ -207,6 +208,88 @@ void PointerDataPacketConverter::ConvertPointerData(
207208
converted_pointers.push_back(pointer_data);
208209
break;
209210
}
211+
case PointerData::Change::kPanZoomStart: {
212+
// Makes sure we have an existing pointer
213+
auto iter = states_.find(pointer_data.device);
214+
PointerState state;
215+
if (iter == states_.end()) {
216+
// Synthesizes add event if the pointer is not previously added.
217+
PointerData synthesized_add_event = pointer_data;
218+
synthesized_add_event.change = PointerData::Change::kAdd;
219+
synthesized_add_event.synthesized = 1;
220+
synthesized_add_event.buttons = 0;
221+
state = EnsurePointerState(synthesized_add_event);
222+
converted_pointers.push_back(synthesized_add_event);
223+
} else {
224+
state = iter->second;
225+
}
226+
FML_DCHECK(!state.is_down);
227+
FML_DCHECK(!state.is_pan_zoom_active);
228+
if (LocationNeedsUpdate(pointer_data, state)) {
229+
// Synthesizes a hover event if the location does not match.
230+
PointerData synthesized_hover_event = pointer_data;
231+
synthesized_hover_event.change = PointerData::Change::kHover;
232+
synthesized_hover_event.synthesized = 1;
233+
synthesized_hover_event.buttons = 0;
234+
235+
UpdateDeltaAndState(synthesized_hover_event, state);
236+
converted_pointers.push_back(synthesized_hover_event);
237+
}
238+
239+
UpdatePointerIdentifier(pointer_data, state, true);
240+
state.is_pan_zoom_active = true;
241+
state.pan_x = 0;
242+
state.pan_y = 0;
243+
state.scale = 1;
244+
state.rotation = 0;
245+
states_[pointer_data.device] = state;
246+
converted_pointers.push_back(pointer_data);
247+
break;
248+
}
249+
case PointerData::Change::kPanZoomUpdate: {
250+
// Makes sure we have an existing pointer in pan_zoom_active state
251+
auto iter = states_.find(pointer_data.device);
252+
FML_DCHECK(iter != states_.end());
253+
PointerState state = iter->second;
254+
FML_DCHECK(!state.is_down);
255+
FML_DCHECK(state.is_pan_zoom_active);
256+
257+
UpdatePointerIdentifier(pointer_data, state, false);
258+
UpdateDeltaAndState(pointer_data, state);
259+
260+
converted_pointers.push_back(pointer_data);
261+
break;
262+
}
263+
case PointerData::Change::kPanZoomEnd: {
264+
// Makes sure we have an existing pointer in pan_zoom_active state
265+
auto iter = states_.find(pointer_data.device);
266+
FML_DCHECK(iter != states_.end());
267+
PointerState state = iter->second;
268+
FML_DCHECK(state.is_pan_zoom_active);
269+
270+
UpdatePointerIdentifier(pointer_data, state, false);
271+
272+
if (LocationNeedsUpdate(pointer_data, state)) {
273+
// Synthesizes an update event if the location does not match.
274+
PointerData synthesized_move_event = pointer_data;
275+
synthesized_move_event.change = PointerData::Change::kPanZoomUpdate;
276+
synthesized_move_event.pan_x = state.pan_x;
277+
synthesized_move_event.pan_y = state.pan_y;
278+
synthesized_move_event.pan_delta_x = 0;
279+
synthesized_move_event.pan_delta_y = 0;
280+
synthesized_move_event.scale = state.scale;
281+
synthesized_move_event.rotation = state.rotation;
282+
synthesized_move_event.synthesized = 1;
283+
284+
UpdateDeltaAndState(synthesized_move_event, state);
285+
converted_pointers.push_back(synthesized_move_event);
286+
}
287+
288+
state.is_pan_zoom_active = false;
289+
states_[pointer_data.device] = state;
290+
converted_pointers.push_back(pointer_data);
291+
break;
292+
}
210293
default: {
211294
converted_pointers.push_back(pointer_data);
212295
break;
@@ -261,8 +344,11 @@ PointerState PointerDataPacketConverter::EnsurePointerState(
261344
PointerState state;
262345
state.pointer_identifier = 0;
263346
state.is_down = false;
347+
state.is_pan_zoom_active = false;
264348
state.physical_x = pointer_data.physical_x;
265349
state.physical_y = pointer_data.physical_y;
350+
state.pan_x = pointer_data.pan_x;
351+
state.pan_y = pointer_data.pan_y;
266352
states_[pointer_data.device] = state;
267353
return state;
268354
}
@@ -271,8 +357,14 @@ void PointerDataPacketConverter::UpdateDeltaAndState(PointerData& pointer_data,
271357
PointerState& state) {
272358
pointer_data.physical_delta_x = pointer_data.physical_x - state.physical_x;
273359
pointer_data.physical_delta_y = pointer_data.physical_y - state.physical_y;
360+
pointer_data.pan_delta_x = pointer_data.pan_x - state.pan_x;
361+
pointer_data.pan_delta_y = pointer_data.pan_y - state.pan_y;
274362
state.physical_x = pointer_data.physical_x;
275363
state.physical_y = pointer_data.physical_y;
364+
state.pan_x = pointer_data.pan_x;
365+
state.pan_y = pointer_data.pan_y;
366+
state.scale = pointer_data.scale;
367+
state.rotation = pointer_data.rotation;
276368
states_[pointer_data.device] = state;
277369
}
278370

lib/ui/window/pointer_data_packet_converter.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,13 @@ namespace flutter {
3030
struct PointerState {
3131
int64_t pointer_identifier;
3232
bool is_down;
33+
bool is_pan_zoom_active;
3334
double physical_x;
3435
double physical_y;
36+
double pan_x;
37+
double pan_y;
38+
double scale;
39+
double rotation;
3540
int64_t buttons;
3641
};
3742

0 commit comments

Comments
 (0)