// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"

#include <Carbon/Carbon.h>

#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h"
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterAppDelegate.h"
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterKeyPrimaryResponder.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterKeyboardManager.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderer.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputSemanticsObject.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h"
#import "flutter/shell/platform/embedder/embedder.h"

namespace {
using flutter::KeyboardLayoutNotifier;
using flutter::LayoutClue;

// Use different device ID for mouse and pan/zoom events, since we can't differentiate the actual
// device (mouse v.s. trackpad).
static constexpr int32_t kMousePointerDeviceId = 0;
static constexpr int32_t kPointerPanZoomDeviceId = 1;

// A trackpad touch following inertial scrolling should cause an inertia cancel
// event to be issued. Use a window of 50 milliseconds after the scroll to account
// for delays in event propagation observed in macOS Ventura.
static constexpr double kTrackpadTouchInertiaCancelWindowMs = 0.050;

/**
 * State tracking for mouse events, to adapt between the events coming from the system and the
 * events that the embedding API expects.
 */
struct MouseState {
  /**
   * The currently pressed buttons, as represented in FlutterPointerEvent.
   */
  int64_t buttons = 0;

  /**
   * The accumulated gesture pan.
   */
  CGFloat delta_x = 0;
  CGFloat delta_y = 0;

  /**
   * The accumulated gesture zoom scale.
   */
  CGFloat scale = 0;

  /**
   * The accumulated gesture rotation.
   */
  CGFloat rotation = 0;

  /**
   * Whether or not a kAdd event has been sent (or sent again since the last kRemove if tracking is
   * enabled). Used to determine whether to send a kAdd event before sending an incoming mouse
   * event, since Flutter expects pointers to be added before events are sent for them.
   */
  bool flutter_state_is_added = false;

  /**
   * Whether or not a kDown has been sent since the last kAdd/kUp.
   */
  bool flutter_state_is_down = false;

  /**
   * Whether or not mouseExited: was received while a button was down. Cocoa's behavior when
   * dragging out of a tracked area is to send an exit, then keep sending drag events until the last
   * button is released. Flutter doesn't expect to receive events after a kRemove, so the kRemove
   * for the exit needs to be delayed until after the last mouse button is released. If cursor
   * returns back to the window while still dragging, the flag is cleared in mouseEntered:.
   */
  bool has_pending_exit = false;

  /**
   * Pan gesture is currently sending us events.
   */
  bool pan_gesture_active = false;

  /**
   * Scale gesture is currently sending us events.
   */
  bool scale_gesture_active = false;

  /**
   * Rotate gesture is currently sending use events.
   */
  bool rotate_gesture_active = false;

  /**
   * Time of last scroll momentum event.
   */
  NSTimeInterval last_scroll_momentum_changed_time = 0;

  /**
   * Resets all gesture state to default values.
   */
  void GestureReset() {
    delta_x = 0;
    delta_y = 0;
    scale = 0;
    rotation = 0;
  }

  /**
   * Resets all state to default values.
   */
  void Reset() {
    flutter_state_is_added = false;
    flutter_state_is_down = false;
    has_pending_exit = false;
    buttons = 0;
    GestureReset();
  }
};

/**
 * Returns the current Unicode layout data (kTISPropertyUnicodeKeyLayoutData).
 *
 * To use the returned data, convert it to CFDataRef first, finds its bytes
 * with CFDataGetBytePtr, then reinterpret it into const UCKeyboardLayout*.
 * It's returned in NSData* to enable auto reference count.
 */
NSData* currentKeyboardLayoutData() {
  TISInputSourceRef source = TISCopyCurrentKeyboardInputSource();
  CFTypeRef layout_data = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData);
  if (layout_data == nil) {
    CFRelease(source);
    // TISGetInputSourceProperty returns null with Japanese keyboard layout.
    // Using TISCopyCurrentKeyboardLayoutInputSource to fix NULL return.
    // https://github.com/microsoft/node-native-keymap/blob/5f0699ded00179410a14c0e1b0e089fe4df8e130/src/keyboard_mac.mm#L91
    source = TISCopyCurrentKeyboardLayoutInputSource();
    layout_data = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData);
  }
  return (__bridge_transfer NSData*)CFRetain(layout_data);
}

}  // namespace

#pragma mark - Private interface declaration.

/**
 * FlutterViewWrapper is a convenience class that wraps a FlutterView and provides
 * a mechanism to attach AppKit views such as FlutterTextField without affecting
 * the accessibility subtree of the wrapped FlutterView itself.
 *
 * The FlutterViewController uses this class to create its content view. When
 * any of the accessibility services (e.g. VoiceOver) is turned on, the accessibility
 * bridge creates FlutterTextFields that interact with the service. The bridge has to
 * attach the FlutterTextField somewhere in the view hierarchy in order for the
 * FlutterTextField to interact correctly with VoiceOver. Those FlutterTextFields
 * will be attached to this view so that they won't affect the accessibility subtree
 * of FlutterView.
 */
@interface FlutterViewWrapper : NSView

- (void)setBackgroundColor:(NSColor*)color;

@end

/**
 * Private interface declaration for FlutterViewController.
 */
@interface FlutterViewController () <FlutterViewReshapeListener>

/**
 * The tracking area used to generate hover events, if enabled.
 */
@property(nonatomic) NSTrackingArea* trackingArea;

/**
 * The current state of the mouse and the sent mouse events.
 */
@property(nonatomic) MouseState mouseState;

/**
 * Event monitor for keyUp events.
 */
@property(nonatomic) id keyUpMonitor;

/**
 * Pointer to a keyboard manager, a hub that manages how key events are
 * dispatched to various Flutter key responders, and whether the event is
 * propagated to the next NSResponder.
 */
@property(nonatomic, readonly, nonnull) FlutterKeyboardManager* keyboardManager;

@property(nonatomic) KeyboardLayoutNotifier keyboardLayoutNotifier;

@property(nonatomic) NSData* keyboardLayoutData;

/**
 * Starts running |engine|, including any initial setup.
 */
- (BOOL)launchEngine;

/**
 * Updates |trackingArea| for the current tracking settings, creating it with
 * the correct mode if tracking is enabled, or removing it if not.
 */
- (void)configureTrackingArea;

/**
 * Creates and registers keyboard related components.
 */
- (void)initializeKeyboard;

/**
 * Calls dispatchMouseEvent:phase: with a phase determined by self.mouseState.
 *
 * mouseState.buttons should be updated before calling this method.
 */
- (void)dispatchMouseEvent:(nonnull NSEvent*)event;

/**
 * Calls dispatchMouseEvent:phase: with a phase determined by event.phase.
 */
- (void)dispatchGestureEvent:(nonnull NSEvent*)event;

/**
 * Converts |event| to a FlutterPointerEvent with the given phase, and sends it to the engine.
 */
- (void)dispatchMouseEvent:(nonnull NSEvent*)event phase:(FlutterPointerPhase)phase;

/**
 * Called when the active keyboard input source changes.
 *
 * Input sources may be simple keyboard layouts, or more complex input methods involving an IME,
 * such as Chinese, Japanese, and Korean.
 */
- (void)onKeyboardLayoutChanged;

@end

#pragma mark - Private dependant functions

namespace {
void OnKeyboardLayoutChanged(CFNotificationCenterRef center,
                             void* observer,
                             CFStringRef name,
                             const void* object,
                             CFDictionaryRef userInfo) {
  FlutterViewController* controller = (__bridge FlutterViewController*)observer;
  if (controller != nil) {
    [controller onKeyboardLayoutChanged];
  }
}
}  // namespace

#pragma mark - FlutterViewWrapper implementation.

@implementation FlutterViewWrapper {
  FlutterView* _flutterView;
}

- (instancetype)initWithFlutterView:(FlutterView*)view {
  self = [super initWithFrame:NSZeroRect];
  if (self) {
    _flutterView = view;
    view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
    [self addSubview:view];
  }
  return self;
}

- (void)setBackgroundColor:(NSColor*)color {
  [_flutterView setBackgroundColor:color];
}

- (NSArray*)accessibilityChildren {
  return @[ _flutterView ];
}

@end

#pragma mark - FlutterViewController implementation.

@implementation FlutterViewController {
  // The project to run in this controller's engine.
  FlutterDartProject* _project;
}

@dynamic view;

/**
 * Performs initialization that's common between the different init paths.
 */
static void CommonInit(FlutterViewController* controller) {
  if (!controller->_engine) {
    controller->_engine = [[FlutterEngine alloc] initWithName:@"io.flutter"
                                                      project:controller->_project
                                       allowHeadlessExecution:NO];
  }
  controller->_mouseTrackingMode = FlutterMouseTrackingModeInKeyWindow;
  controller->_textInputPlugin = [[FlutterTextInputPlugin alloc] initWithViewController:controller];
  // macOS fires this message when changing IMEs.
  CFNotificationCenterRef cfCenter = CFNotificationCenterGetDistributedCenter();
  __weak FlutterViewController* weakSelf = controller;
  CFNotificationCenterAddObserver(cfCenter, (__bridge void*)weakSelf, OnKeyboardLayoutChanged,
                                  kTISNotifySelectedKeyboardInputSourceChanged, NULL,
                                  CFNotificationSuspensionBehaviorDeliverImmediately);
}

- (instancetype)initWithCoder:(NSCoder*)coder {
  self = [super initWithCoder:coder];
  NSAssert(self, @"Super init cannot be nil");

  CommonInit(self);
  return self;
}

- (instancetype)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil {
  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  NSAssert(self, @"Super init cannot be nil");

  CommonInit(self);
  return self;
}

- (instancetype)initWithProject:(nullable FlutterDartProject*)project {
  self = [super initWithNibName:nil bundle:nil];
  NSAssert(self, @"Super init cannot be nil");

  _project = project;
  CommonInit(self);
  return self;
}

- (instancetype)initWithEngine:(nonnull FlutterEngine*)engine
                       nibName:(nullable NSString*)nibName
                        bundle:(nullable NSBundle*)nibBundle {
  NSAssert(engine != nil, @"Engine is required");
  NSAssert(engine.viewController == nil,
           @"The supplied FlutterEngine is already used with FlutterViewController "
            "instance. One instance of the FlutterEngine can only be attached to one "
            "FlutterViewController at a time. Set FlutterEngine.viewController "
            "to nil before attaching it to another FlutterViewController.");

  self = [super initWithNibName:nibName bundle:nibBundle];
  if (self) {
    _engine = engine;
    CommonInit(self);
    if (engine.running) {
      [self loadView];
      engine.viewController = self;
      [self initializeKeyboard];
    }
  }

  return self;
}

- (BOOL)isDispatchingKeyEvent:(NSEvent*)event {
  return [_keyboardManager isDispatchingKeyEvent:event];
}

- (void)loadView {
  FlutterView* flutterView;
  id<MTLDevice> device = _engine.renderer.device;
  id<MTLCommandQueue> commandQueue = _engine.renderer.commandQueue;
  if (!device || !commandQueue) {
    NSLog(@"Unable to create FlutterView; no MTLDevice or MTLCommandQueue available.");
    return;
  }
  flutterView = [[FlutterView alloc] initWithMTLDevice:device
                                          commandQueue:commandQueue
                                       reshapeListener:self];
  if (_backgroundColor != nil) {
    [flutterView setBackgroundColor:_backgroundColor];
  }
  FlutterViewWrapper* wrapperView = [[FlutterViewWrapper alloc] initWithFlutterView:flutterView];
  self.view = wrapperView;
  _flutterView = flutterView;
}

- (void)viewDidLoad {
  [self configureTrackingArea];
  [self.view setAllowedTouchTypes:NSTouchTypeMaskIndirect];
  [self.view setWantsRestingTouches:YES];
}

- (void)viewWillAppear {
  [super viewWillAppear];
  if (!_engine.running) {
    [self launchEngine];
  }
  [self listenForMetaModifiedKeyUpEvents];
}

- (void)viewWillDisappear {
  // Per Apple's documentation, it is discouraged to call removeMonitor: in dealloc, and it's
  // recommended to be called earlier in the lifecycle.
  [NSEvent removeMonitor:_keyUpMonitor];
  _keyUpMonitor = nil;
}

- (void)dealloc {
  _engine.viewController = nil;
  CFNotificationCenterRef cfCenter = CFNotificationCenterGetDistributedCenter();
  CFNotificationCenterRemoveEveryObserver(cfCenter, (__bridge void*)self);
}

#pragma mark - Public methods

- (void)setMouseTrackingMode:(FlutterMouseTrackingMode)mode {
  if (_mouseTrackingMode == mode) {
    return;
  }
  _mouseTrackingMode = mode;
  [self configureTrackingArea];
}

- (void)setBackgroundColor:(NSColor*)color {
  _backgroundColor = color;
  [_flutterView setBackgroundColor:_backgroundColor];
}

- (void)onPreEngineRestart {
  [self initializeKeyboard];
}

#pragma mark - Private methods

- (BOOL)launchEngine {
  [self initializeKeyboard];

  _engine.viewController = self;
  if (![_engine runWithEntrypoint:nil]) {
    return NO;
  }
  return YES;
}

// macOS does not call keyUp: on a key while the command key is pressed. This results in a loss
// of a key event once the modified key is released. This method registers the
// ViewController as a listener for a keyUp event before it's handled by NSApplication, and should
// NOT modify the event to avoid any unexpected behavior.
- (void)listenForMetaModifiedKeyUpEvents {
  if (_keyUpMonitor != nil) {
    // It is possible for [NSViewController viewWillAppear] to be invoked multiple times
    // in a row. https://github.com/flutter/flutter/issues/105963
    return;
  }
  FlutterViewController* __weak weakSelf = self;
  _keyUpMonitor = [NSEvent
      addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
                                   handler:^NSEvent*(NSEvent* event) {
                                     // Intercept keyUp only for events triggered on the current
                                     // view or textInputPlugin.
                                     NSResponder* firstResponder = [[event window] firstResponder];
                                     if (weakSelf.viewLoaded && weakSelf.flutterView &&
                                         (firstResponder == weakSelf.flutterView ||
                                          firstResponder == weakSelf.textInputPlugin) &&
                                         ([event modifierFlags] & NSEventModifierFlagCommand) &&
                                         ([event type] == NSEventTypeKeyUp)) {
                                       [weakSelf keyUp:event];
                                     }
                                     return event;
                                   }];
}

- (void)configureTrackingArea {
  if (!self.viewLoaded) {
    // The viewDidLoad will call configureTrackingArea again when
    // the view is actually loaded.
    return;
  }
  if (_mouseTrackingMode != FlutterMouseTrackingModeNone && self.flutterView) {
    NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
                                    NSTrackingInVisibleRect | NSTrackingEnabledDuringMouseDrag;
    switch (_mouseTrackingMode) {
      case FlutterMouseTrackingModeInKeyWindow:
        options |= NSTrackingActiveInKeyWindow;
        break;
      case FlutterMouseTrackingModeInActiveApp:
        options |= NSTrackingActiveInActiveApp;
        break;
      case FlutterMouseTrackingModeAlways:
        options |= NSTrackingActiveAlways;
        break;
      default:
        NSLog(@"Error: Unrecognized mouse tracking mode: %ld", _mouseTrackingMode);
        return;
    }
    _trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
                                                 options:options
                                                   owner:self
                                                userInfo:nil];
    [self.flutterView addTrackingArea:_trackingArea];
  } else if (_trackingArea) {
    [self.flutterView removeTrackingArea:_trackingArea];
    _trackingArea = nil;
  }
}

- (void)initializeKeyboard {
  // TODO(goderbauer): Seperate keyboard/textinput stuff into ViewController specific and Engine
  // global parts. Move the global parts to FlutterEngine.
  __weak FlutterViewController* weakSelf = self;
  _keyboardManager = [[FlutterKeyboardManager alloc] initWithViewDelegate:weakSelf];
}

- (void)dispatchMouseEvent:(nonnull NSEvent*)event {
  FlutterPointerPhase phase = _mouseState.buttons == 0
                                  ? (_mouseState.flutter_state_is_down ? kUp : kHover)
                                  : (_mouseState.flutter_state_is_down ? kMove : kDown);
  [self dispatchMouseEvent:event phase:phase];
}

- (void)dispatchGestureEvent:(nonnull NSEvent*)event {
  if (event.phase == NSEventPhaseBegan || event.phase == NSEventPhaseMayBegin) {
    [self dispatchMouseEvent:event phase:kPanZoomStart];
  } else if (event.phase == NSEventPhaseChanged) {
    [self dispatchMouseEvent:event phase:kPanZoomUpdate];
  } else if (event.phase == NSEventPhaseEnded || event.phase == NSEventPhaseCancelled) {
    [self dispatchMouseEvent:event phase:kPanZoomEnd];
  } else if (event.phase == NSEventPhaseNone && event.momentumPhase == NSEventPhaseNone) {
    [self dispatchMouseEvent:event phase:kHover];
  } else {
    // Waiting until the first momentum change event is a workaround for an issue where
    // touchesBegan: is called unexpectedly while in low power mode within the interval between
    // momentum start and the first momentum change.
    if (event.momentumPhase == NSEventPhaseChanged) {
      _mouseState.last_scroll_momentum_changed_time = event.timestamp;
    }
    // Skip momentum update events, the framework will generate scroll momentum.
    NSAssert(event.momentumPhase != NSEventPhaseNone,
             @"Received gesture event with unexpected phase");
  }
}

- (void)dispatchMouseEvent:(NSEvent*)event phase:(FlutterPointerPhase)phase {
  NSAssert(self.viewLoaded, @"View must be loaded before it handles the mouse event");
  // There are edge cases where the system will deliver enter out of order relative to other
  // events (e.g., drag out and back in, release, then click; mouseDown: will be called before
  // mouseEntered:). Discard those events, since the add will already have been synthesized.
  if (_mouseState.flutter_state_is_added && phase == kAdd) {
    return;
  }

  // Multiple gesture recognizers could be active at once, we can't send multiple kPanZoomStart.
  // For example: rotation and magnification.
  if (phase == kPanZoomStart) {
    bool gestureAlreadyDown = _mouseState.pan_gesture_active || _mouseState.scale_gesture_active ||
                              _mouseState.rotate_gesture_active;
    if (event.type == NSEventTypeScrollWheel) {
      _mouseState.pan_gesture_active = true;
      // Ensure scroll inertia cancel event is not sent afterwards.
      _mouseState.last_scroll_momentum_changed_time = 0;
    } else if (event.type == NSEventTypeMagnify) {
      _mouseState.scale_gesture_active = true;
    } else if (event.type == NSEventTypeRotate) {
      _mouseState.rotate_gesture_active = true;
    }
    if (gestureAlreadyDown) {
      return;
    }
  }
  if (phase == kPanZoomEnd) {
    if (event.type == NSEventTypeScrollWheel) {
      _mouseState.pan_gesture_active = false;
    } else if (event.type == NSEventTypeMagnify) {
      _mouseState.scale_gesture_active = false;
    } else if (event.type == NSEventTypeRotate) {
      _mouseState.rotate_gesture_active = false;
    }
    if (_mouseState.pan_gesture_active || _mouseState.scale_gesture_active ||
        _mouseState.rotate_gesture_active) {
      return;
    }
  }

  // If a pointer added event hasn't been sent, synthesize one using this event for the basic
  // information.
  if (!_mouseState.flutter_state_is_added && phase != kAdd) {
    // Only the values extracted for use in flutterEvent below matter, the rest are dummy values.
    NSEvent* addEvent = [NSEvent enterExitEventWithType:NSEventTypeMouseEntered
                                               location:event.locationInWindow
                                          modifierFlags:0
                                              timestamp:event.timestamp
                                           windowNumber:event.windowNumber
                                                context:nil
                                            eventNumber:0
                                         trackingNumber:0
                                               userData:NULL];
    [self dispatchMouseEvent:addEvent phase:kAdd];
  }

  NSPoint locationInView = [self.flutterView convertPoint:event.locationInWindow fromView:nil];
  NSPoint locationInBackingCoordinates = [self.flutterView convertPointToBacking:locationInView];
  int32_t device = kMousePointerDeviceId;
  FlutterPointerDeviceKind deviceKind = kFlutterPointerDeviceKindMouse;
  if (phase == kPanZoomStart || phase == kPanZoomUpdate || phase == kPanZoomEnd) {
    device = kPointerPanZoomDeviceId;
    deviceKind = kFlutterPointerDeviceKindTrackpad;
  }
  FlutterPointerEvent flutterEvent = {
      .struct_size = sizeof(flutterEvent),
      .phase = phase,
      .timestamp = static_cast<size_t>(event.timestamp * USEC_PER_SEC),
      .x = locationInBackingCoordinates.x,
      .y = -locationInBackingCoordinates.y,  // convertPointToBacking makes this negative.
      .device = device,
      .device_kind = deviceKind,
      // If a click triggered a synthesized kAdd, don't pass the buttons in that event.
      .buttons = phase == kAdd ? 0 : _mouseState.buttons,
  };

  if (phase == kPanZoomUpdate) {
    if (event.type == NSEventTypeScrollWheel) {
      _mouseState.delta_x += event.scrollingDeltaX * self.flutterView.layer.contentsScale;
      _mouseState.delta_y += event.scrollingDeltaY * self.flutterView.layer.contentsScale;
    } else if (event.type == NSEventTypeMagnify) {
      _mouseState.scale += event.magnification;
    } else if (event.type == NSEventTypeRotate) {
      _mouseState.rotation += event.rotation * (-M_PI / 180.0);
    }
    flutterEvent.pan_x = _mouseState.delta_x;
    flutterEvent.pan_y = _mouseState.delta_y;
    // Scale value needs to be normalized to range 0->infinity.
    flutterEvent.scale = pow(2.0, _mouseState.scale);
    flutterEvent.rotation = _mouseState.rotation;
  } else if (phase == kPanZoomEnd) {
    _mouseState.GestureReset();
  } else if (phase != kPanZoomStart && event.type == NSEventTypeScrollWheel) {
    flutterEvent.signal_kind = kFlutterPointerSignalKindScroll;

    double pixelsPerLine = 1.0;
    if (!event.hasPreciseScrollingDeltas) {
      // The scrollingDelta needs to be multiplied by the line height.
      // CGEventSourceGetPixelsPerLine() will return 10, which will result in
      // scrolling that is noticeably slower than in other applications.
      // Using 40.0 as the multiplier to match Chromium.
      // See https://source.chromium.org/chromium/chromium/src/+/main:ui/events/cocoa/events_mac.mm
      pixelsPerLine = 40.0;
    }
    double scaleFactor = self.flutterView.layer.contentsScale;
    // 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;
    }
  }

  [_keyboardManager syncModifiersIfNeeded:event.modifierFlags timestamp:event.timestamp];
  [_engine sendPointerEvent:flutterEvent];

  // Update tracking of state as reported to Flutter.
  if (phase == kDown) {
    _mouseState.flutter_state_is_down = true;
  } else if (phase == kUp) {
    _mouseState.flutter_state_is_down = false;
    if (_mouseState.has_pending_exit) {
      [self dispatchMouseEvent:event phase:kRemove];
      _mouseState.has_pending_exit = false;
    }
  } else if (phase == kAdd) {
    _mouseState.flutter_state_is_added = true;
  } else if (phase == kRemove) {
    _mouseState.Reset();
  }
}

- (void)onAccessibilityStatusChanged:(BOOL)enabled {
  if (!enabled && self.viewLoaded && [_textInputPlugin isFirstResponder]) {
    // Normally TextInputPlugin, when editing, is child of FlutterViewWrapper.
    // When accessiblity is enabled the TextInputPlugin gets added as an indirect
    // child to FlutterTextField. When disabling the plugin needs to be reparented
    // back.
    [self.view addSubview:_textInputPlugin];
  }
}

- (void)onKeyboardLayoutChanged {
  _keyboardLayoutData = nil;
  if (_keyboardLayoutNotifier != nil) {
    _keyboardLayoutNotifier();
  }
}

#pragma mark - FlutterViewReshapeListener

/**
 * Responds to view reshape by notifying the engine of the change in dimensions.
 */
- (void)viewDidReshape:(NSView*)view {
  [_engine updateWindowMetrics];
}

#pragma mark - FlutterPluginRegistry

- (id<FlutterPluginRegistrar>)registrarForPlugin:(NSString*)pluginName {
  return [_engine registrarForPlugin:pluginName];
}

#pragma mark - FlutterKeyboardViewDelegate

- (void)sendKeyEvent:(const FlutterKeyEvent&)event
            callback:(nullable FlutterKeyEventCallback)callback
            userData:(nullable void*)userData {
  [_engine sendKeyEvent:event callback:callback userData:userData];
}

- (id<FlutterBinaryMessenger>)getBinaryMessenger {
  return _engine.binaryMessenger;
}

- (BOOL)onTextInputKeyEvent:(nonnull NSEvent*)event {
  return [_textInputPlugin handleKeyEvent:event];
}

- (void)subscribeToKeyboardLayoutChange:(nullable KeyboardLayoutNotifier)callback {
  _keyboardLayoutNotifier = callback;
}

- (LayoutClue)lookUpLayoutForKeyCode:(uint16_t)keyCode shift:(BOOL)shift {
  if (_keyboardLayoutData == nil) {
    _keyboardLayoutData = currentKeyboardLayoutData();
  }
  const UCKeyboardLayout* layout = reinterpret_cast<const UCKeyboardLayout*>(
      CFDataGetBytePtr((__bridge CFDataRef)_keyboardLayoutData));

  UInt32 deadKeyState = 0;
  UniCharCount stringLength = 0;
  UniChar resultChar;

  UInt32 modifierState = ((shift ? shiftKey : 0) >> 8) & 0xFF;
  UInt32 keyboardType = LMGetKbdLast();

  bool isDeadKey = false;
  OSStatus status =
      UCKeyTranslate(layout, keyCode, kUCKeyActionDown, modifierState, keyboardType,
                     kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &stringLength, &resultChar);
  // For dead keys, press the same key again to get the printable representation of the key.
  if (status == noErr && stringLength == 0 && deadKeyState != 0) {
    isDeadKey = true;
    status =
        UCKeyTranslate(layout, keyCode, kUCKeyActionDown, modifierState, keyboardType,
                       kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &stringLength, &resultChar);
  }

  if (status == noErr && stringLength == 1 && !std::iscntrl(resultChar)) {
    return LayoutClue{resultChar, isDeadKey};
  }
  return LayoutClue{0, false};
}

#pragma mark - NSResponder

- (BOOL)acceptsFirstResponder {
  return YES;
}

- (void)keyDown:(NSEvent*)event {
  [_keyboardManager handleEvent:event];
}

- (void)keyUp:(NSEvent*)event {
  [_keyboardManager handleEvent:event];
}

- (void)flagsChanged:(NSEvent*)event {
  [_keyboardManager handleEvent:event];
}

- (void)mouseEntered:(NSEvent*)event {
  if (_mouseState.has_pending_exit) {
    _mouseState.has_pending_exit = false;
  } else {
    [self dispatchMouseEvent:event phase:kAdd];
  }
}

- (void)mouseExited:(NSEvent*)event {
  if (_mouseState.buttons != 0) {
    _mouseState.has_pending_exit = true;
    return;
  }
  [self dispatchMouseEvent:event phase:kRemove];
}

- (void)mouseDown:(NSEvent*)event {
  _mouseState.buttons |= kFlutterPointerButtonMousePrimary;
  [self dispatchMouseEvent:event];
}

- (void)mouseUp:(NSEvent*)event {
  _mouseState.buttons &= ~static_cast<uint64_t>(kFlutterPointerButtonMousePrimary);
  [self dispatchMouseEvent:event];
}

- (void)mouseDragged:(NSEvent*)event {
  [self dispatchMouseEvent:event];
}

- (void)rightMouseDown:(NSEvent*)event {
  _mouseState.buttons |= kFlutterPointerButtonMouseSecondary;
  [self dispatchMouseEvent:event];
}

- (void)rightMouseUp:(NSEvent*)event {
  _mouseState.buttons &= ~static_cast<uint64_t>(kFlutterPointerButtonMouseSecondary);
  [self dispatchMouseEvent:event];
}

- (void)rightMouseDragged:(NSEvent*)event {
  [self dispatchMouseEvent:event];
}

- (void)otherMouseDown:(NSEvent*)event {
  _mouseState.buttons |= (1 << event.buttonNumber);
  [self dispatchMouseEvent:event];
}

- (void)otherMouseUp:(NSEvent*)event {
  _mouseState.buttons &= ~static_cast<uint64_t>(1 << event.buttonNumber);
  [self dispatchMouseEvent:event];
}

- (void)otherMouseDragged:(NSEvent*)event {
  [self dispatchMouseEvent:event];
}

- (void)mouseMoved:(NSEvent*)event {
  [self dispatchMouseEvent:event];
}

- (void)scrollWheel:(NSEvent*)event {
  [self dispatchGestureEvent:event];
}

- (void)magnifyWithEvent:(NSEvent*)event {
  [self dispatchGestureEvent:event];
}

- (void)rotateWithEvent:(NSEvent*)event {
  [self dispatchGestureEvent:event];
}

- (void)swipeWithEvent:(NSEvent*)event {
  // Not needed, it's handled by scrollWheel.
}

- (void)touchesBeganWithEvent:(NSEvent*)event {
  NSTouch* touch = event.allTouches.anyObject;
  if (touch != nil) {
    if ((event.timestamp - _mouseState.last_scroll_momentum_changed_time) <
        kTrackpadTouchInertiaCancelWindowMs) {
      // The trackpad has been touched following a scroll momentum event.
      // A scroll inertia cancel message should be sent to the framework.
      NSPoint locationInView = [self.flutterView convertPoint:event.locationInWindow fromView:nil];
      NSPoint locationInBackingCoordinates =
          [self.flutterView convertPointToBacking:locationInView];
      FlutterPointerEvent flutterEvent = {
          .struct_size = sizeof(flutterEvent),
          .timestamp = static_cast<size_t>(event.timestamp * USEC_PER_SEC),
          .x = locationInBackingCoordinates.x,
          .y = -locationInBackingCoordinates.y,  // convertPointToBacking makes this negative.
          .device = kPointerPanZoomDeviceId,
          .signal_kind = kFlutterPointerSignalKindScrollInertiaCancel,
          .device_kind = kFlutterPointerDeviceKindTrackpad,
      };

      [_engine sendPointerEvent:flutterEvent];
      // Ensure no further scroll inertia cancel event will be sent.
      _mouseState.last_scroll_momentum_changed_time = 0;
    }
  }
}

@end
