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

Undo axes flip on Mac when shift+scroll-wheel #38338

Merged
merged 11 commits into from
Jan 10, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -643,8 +643,23 @@ - (void)dispatchMouseEvent:(NSEvent*)event phase:(FlutterPointerPhase)phase {
pixelsPerLine = 40.0;
}
double scaleFactor = self.flutterView.layer.contentsScale;
flutterEvent.scroll_delta_x = -event.scrollingDeltaX * pixelsPerLine * scaleFactor;
flutterEvent.scroll_delta_y = -event.scrollingDeltaY * pixelsPerLine * scaleFactor;
// When mouse input is received while shift is pressed (regardless of
// any other pressed keys), Mac automatically flips the axis. Other
// platforms do not do this, so we flip it back to normalize the input
// received by the framework. The keyboard+mouse-scroll mechanism is exposed
// in the ScrollBehavior of the framework so developers can customize the
// behavior.
// At time of change, Apple does not expose any other type of API or signal
// that the X/Y axes have been flipped.
double scaledDeltaX = -event.scrollingDeltaX * pixelsPerLine * scaleFactor;
double scaledDeltaY = -event.scrollingDeltaY * pixelsPerLine * scaleFactor;
if (event.modifierFlags & NSShiftKeyMask) {
flutterEvent.scroll_delta_x = scaledDeltaY;
flutterEvent.scroll_delta_y = scaledDeltaX;
} else {
flutterEvent.scroll_delta_x = scaledDeltaX;
flutterEvent.scroll_delta_y = scaledDeltaY;
}
}
[_engine sendPointerEvent:flutterEvent];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,27 @@ - (bool)testTrackpadGesturesAreSentToFramework {
EXPECT_EQ(last_event.scroll_delta_x, -40 * viewController.flutterView.layer.contentsScale);
EXPECT_EQ(last_event.scroll_delta_y, -80 * viewController.flutterView.layer.contentsScale);

// A discrete scroll event should use the PointerSignal system, and flip the
// direction when shift is pressed.
CGEventRef cgEventDiscreteShift =
CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 1, 0);
CGEventSetType(cgEventDiscreteShift, kCGEventScrollWheel);
CGEventSetFlags(cgEventDiscreteShift, kCGEventFlagMaskShift);
CGEventSetIntegerValueField(cgEventDiscreteShift, kCGScrollWheelEventIsContinuous, 0);
CGEventSetIntegerValueField(cgEventDiscreteShift, kCGScrollWheelEventDeltaAxis2,
0); // scroll_delta_x
CGEventSetIntegerValueField(cgEventDiscreteShift, kCGScrollWheelEventDeltaAxis1,
2); // scroll_delta_y

called = false;
[viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventDiscreteShift]];
EXPECT_TRUE(called);
EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindScroll);
// pixelsPerLine is 40.0, direction is reversed and axes have been flipped back.
EXPECT_FLOAT_EQ(last_event.scroll_delta_x, 0.0 * viewController.flutterView.layer.contentsScale);
EXPECT_FLOAT_EQ(last_event.scroll_delta_y,
-80.0 * viewController.flutterView.layer.contentsScale);

// Test for scale events.
// Start gesture.
called = false;
Expand Down