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

Scrollwheel #6228

Closed
wants to merge 10 commits into from
Closed
13 changes: 11 additions & 2 deletions lib/ui/hooks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,13 @@ void _invoke3<A1, A2, A3>(void callback(A1 a1, A2 a2, A3 a3), Zone zone, A1 arg1
//
// * pointer_data.cc
// * FlutterView.java
const int _kPointerDataFieldCount = 19;
// * pointer_data.h
// * pointer.dart
//
// While we're only sending 21 values across, we leave this as 22 due to a bug that
// writes the last 8 bytes to 0 after a few hundred calls. The last value in the packet
// then is not written to any variable.
const int _kPointerDataFieldCount = 22;

PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
const int kStride = Int64List.bytesPerElement;
Expand Down Expand Up @@ -208,7 +214,10 @@ PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
radiusMin: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
radiusMax: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
orientation: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
tilt: packet.getFloat64(kStride * offset++, _kFakeHostEndian)
tilt: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
scrollDeltaX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
scrollDeltaY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
sentinal: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
Copy link
Member

Choose a reason for hiding this comment

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

The error happens when reading from the packet right? do you need to explicitly pass it or can you just ignore the last float?

);
assert(offset == (i + 1) * _kPointerDataFieldCount);
}
Expand Down
29 changes: 26 additions & 3 deletions lib/ui/pointer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ enum PointerChange {

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

/// The pointer has scrolled
scroll,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did you change this back? This is incompatible with the second part of the change I'm working on, to support trackpad gesture scrolling.

My intent is to finish that patch and then put both of them up for review so that the reason for the design choices I made was clear. I think it would make a lot more sense to wait and do it that way than to try to land this one and make changes to it without being able to see how that affects the whole design.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They weren't needed to get the mouse wheel scrolling working, and given that your GestureType only had one type of gesture I felt it wasn't necessary to implement it that way. I also thought you were no longer working on this? Didn't realize you intended to bring it through to the finish line. Anyway, I've stopped working on chrome book stuff for now as we are waiting on various design docs to come through.

}

/// The kind of pointer device.
Expand All @@ -51,7 +54,7 @@ enum PointerDeviceKind {
invertedStylus,

/// An unknown pointer device.
unknown
unknown,
}

/// Information about the state of a pointer.
Expand All @@ -76,7 +79,10 @@ class PointerData {
this.radiusMin: 0.0,
this.radiusMax: 0.0,
this.orientation: 0.0,
this.tilt: 0.0
this.scrollDeltaX: 0.0,
this.scrollDeltaY: 0.0,
this.tilt: 0.0,
this.sentinal: 0.0,
});

/// Time of event dispatch, relative to an arbitrary timeline.
Expand Down Expand Up @@ -190,6 +196,19 @@ class PointerData {
/// the stylus is flat on that surface).
final double tilt;

/// For PointerDeviceKind.gesture with PointerGestureKind.scroll:
///
/// The amount to scroll in the x direction, in physical pixels.
final double scrollDeltaX;

/// For PointerDeviceKind.gesture with PointerGestureKind.scroll:
///
/// The amount to scroll in the y direction, in physical pixels.
final double scrollDeltaY;

/// A final value that is passed so that we are passing more than 21 values in the packet
final double sentinal;
Copy link
Member

Choose a reason for hiding this comment

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

Is there a way you could keep this field private?


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

Expand All @@ -203,6 +222,7 @@ class PointerData {
'physicalX: $physicalX, '
'physicalY: $physicalY, '
'buttons: $buttons, '
'obscured: $obscured'
'pressure: $pressure, '
'pressureMin: $pressureMin, '
'pressureMax: $pressureMax, '
Expand All @@ -213,7 +233,10 @@ class PointerData {
'radiusMin: $radiusMin, '
'radiusMax: $radiusMax, '
'orientation: $orientation, '
'tilt: $tilt'
'tilt: $tilt, '
'scrollDeltaX: $scrollDeltaX, '
'scrollDeltaY: $scrollDeltaY,'
'sentinal: $sentinal'
')';
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/window/pointer_data.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
namespace blink {

// If this value changes, update the pointer data unpacking code in hooks.dart.
static constexpr int kPointerDataFieldCount = 19;
static constexpr int kPointerDataFieldCount = 22;

static_assert(sizeof(PointerData) == sizeof(int64_t) * kPointerDataFieldCount,
"PointerData has the wrong size");
Expand Down
4 changes: 4 additions & 0 deletions lib/ui/window/pointer_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct alignas(8) PointerData {
kDown,
kMove,
kUp,
kScroll,
};

// Must match the PointerDeviceKind enum in pointer.dart.
Expand Down Expand Up @@ -48,7 +49,10 @@ struct alignas(8) PointerData {
double radius_min;
double radius_max;
double orientation;
double scroll_delta_x;
double scroll_delta_y;
double tilt;
double sentinal;

void Clear();
};
Expand Down
1 change: 1 addition & 0 deletions lib/ui/window/window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ void Window::DispatchPointerDataPacket(const PointerDataPacket& packet) {
Dart_Handle data_handle = ToByteData(packet.data());
if (Dart_IsError(data_handle))
return;

DartInvokeField(library_.value(), "_dispatchPointerDataPacket",
{data_handle});
}
Expand Down
56 changes: 53 additions & 3 deletions shell/platform/android/io/flutter/view/FlutterView.java
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
private static final int kPointerChangeDown = 4;
private static final int kPointerChangeMove = 5;
private static final int kPointerChangeUp = 6;
private static final int kPointerChangeScroll = 7;

// Must match the PointerDeviceKind enum in pointer.dart.
private static final int kPointerDeviceKindTouch = 0;
Expand Down Expand Up @@ -401,6 +402,9 @@ private int getPointerChangeForAction(int maskedAction) {
if (maskedAction == MotionEvent.ACTION_CANCEL) {
return kPointerChangeCancel;
}
if (maskedAction == MotionEvent.ACTION_SCROLL) {
return kPointerChangeScroll;
}
return -1;
}

Expand Down Expand Up @@ -428,6 +432,8 @@ private void addPointerForIndex(MotionEvent event, int pointerIndex, ByteBuffer

int pointerKind = getPointerDeviceTypeForToolType(event.getToolType(pointerIndex));

// This is ignored for non-gesture deviced kinds.
Copy link
Member

Choose a reason for hiding this comment

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

not sure what you mean by this


long timeStamp = event.getEventTime() * 1000; // Convert from milliseconds to microseconds.

packet.putLong(timeStamp); // time_stamp
Expand All @@ -437,6 +443,7 @@ private void addPointerForIndex(MotionEvent event, int pointerIndex, ByteBuffer
packet.putDouble(event.getX(pointerIndex)); // physical_x
packet.putDouble(event.getY(pointerIndex)); // physical_y


if (pointerKind == kPointerDeviceKindMouse) {
packet.putLong(event.getButtonState() & 0x1F); // buttons
} else if (pointerKind == kPointerDeviceKindStylus) {
Expand Down Expand Up @@ -468,12 +475,55 @@ private void addPointerForIndex(MotionEvent event, int pointerIndex, ByteBuffer
packet.putDouble(0.0); // radius_max

packet.putDouble(event.getAxisValue(MotionEvent.AXIS_ORIENTATION, pointerIndex)); // orientation

if (pointerKind == kPointerDeviceKindStylus) {
packet.putDouble(event.getAxisValue(MotionEvent.AXIS_TILT, pointerIndex)); // tilt
} else {
packet.putDouble(0.0); // tilt
packet.putDouble(4.0); // tilt
}
packet.putDouble(event.getAxisValue(MotionEvent.AXIS_HSCROLL)); // scroll_delta_x
packet.putDouble(event.getAxisValue(MotionEvent.AXIS_VSCROLL)); // scroll_delta_y

// Dummy value that is needed due to bug in the converter writing the last 8 bytes
// of the packet to 0.
packet.putDouble(0.0);
}

@Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (!isAttached()) {
return false;
}

int maskedAction = event.getAction();
if (maskedAction != MotionEvent.ACTION_SCROLL)
return false;

// TODO(abarth): This version check might not be effective in some
// versions of Android that statically compile code and will be upset
// at the lack of |requestUnbufferedDispatch|. Instead, we should factor
// version-dependent code into separate classes for each supported
// version and dispatch dynamically.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
requestUnbufferedDispatch(event);
}

// These values must match the unpacking code in hooks.dart.
final int kPointerDataFieldCount = 22;
final int kBytePerField = 8;

int pointerCount = event.getPointerCount();

ByteBuffer packet = ByteBuffer.allocateDirect(pointerCount * kPointerDataFieldCount * kBytePerField);
packet.order(ByteOrder.LITTLE_ENDIAN);

for (int p = 0; p < pointerCount; p++) {
addPointerForIndex(event, p, packet);
}

assert packet.position() % (kPointerDataFieldCount * kBytePerField) == 0;
nativeDispatchPointerDataPacket(mNativeView.get(), packet, packet.position());
return true;
}

@Override
Expand All @@ -492,7 +542,7 @@ public boolean onTouchEvent(MotionEvent event) {
}

// These values must match the unpacking code in hooks.dart.
final int kPointerDataFieldCount = 19;
final int kPointerDataFieldCount = 22;
final int kBytePerField = 8;

int pointerCount = event.getPointerCount();
Expand Down
1 change: 1 addition & 0 deletions shell/platform/darwin/desktop/flutter_window.mm
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ - (void)dispatchEvent:(NSEvent*)event phase:(NSEventPhase)phase {
break;
case blink::PointerData::Change::kAdd:
case blink::PointerData::Change::kRemove:
case blink::PointerData::Change::kScroll:
case blink::PointerData::Change::kHover:
FML_DCHECK(!_mouseIsDown);
break;
Expand Down
22 changes: 22 additions & 0 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,18 @@ FlutterResult FlutterEngineSendWindowMetricsEvent(
: kInvalidArguments;
}

// Returns the blink::PointerData::DeviceKind for the given
// FlutterPointerDeviceKind.
inline blink::PointerData::DeviceKind ToPointerDataDeviceKind(
FlutterPointerDeviceKind kind) {
switch (kind) {
case kMouse:
return blink::PointerData::DeviceKind::kMouse;
}
return blink::PointerData::DeviceKind::kMouse;
}

// Returns the blink::PointerData::Change for the given FlutterPointerPhase.
inline blink::PointerData::Change ToPointerDataChange(
FlutterPointerPhase phase) {
switch (phase) {
Expand All @@ -427,6 +439,12 @@ inline blink::PointerData::Change ToPointerDataChange(
return blink::PointerData::Change::kDown;
case kMove:
return blink::PointerData::Change::kMove;
case kAdd:
return blink::PointerData::Change::kAdd;
case kRemove:
return blink::PointerData::Change::kRemove;
case kHover:
return blink::PointerData::Change::kHover;
}
return blink::PointerData::Change::kCancel;
}
Expand All @@ -451,6 +469,10 @@ FlutterResult FlutterEngineSendPointerEvent(FlutterEngine engine,
pointer_data.kind = blink::PointerData::DeviceKind::kMouse;
pointer_data.physical_x = SAFE_ACCESS(current, x, 0.0);
pointer_data.physical_y = SAFE_ACCESS(current, y, 0.0);
pointer_data.kind = ToPointerDataDeviceKind(
SAFE_ACCESS(current, kind, FlutterPointerDeviceKind::kMouse));
pointer_data.scroll_delta_x = SAFE_ACCESS(current, scroll_delta_x, 0.0);
pointer_data.scroll_delta_y = SAFE_ACCESS(current, scroll_delta_y, 0.0);
packet->SetPointerData(i, pointer_data);
current = reinterpret_cast<const FlutterPointerEvent*>(
reinterpret_cast<const uint8_t*>(current) + current->struct_size);
Expand Down
12 changes: 12 additions & 0 deletions shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,20 @@ typedef struct {
double pixel_ratio;
} FlutterWindowMetricsEvent;

// The kind of device generating a pointer event.
typedef enum {
kMouse,
} FlutterPointerDeviceKind;

// The phase of the pointer event.
typedef enum {
kCancel,
kUp,
kDown,
kMove,
kAdd,
kRemove,
kHover,
} FlutterPointerPhase;

typedef struct {
Expand All @@ -124,6 +133,9 @@ typedef struct {
size_t timestamp; // in microseconds.
double x;
double y;
FlutterPointerDeviceKind kind;
double scroll_delta_x;
double scroll_delta_y;
} FlutterPointerEvent;

struct _FlutterPlatformMessageResponseHandle;
Expand Down