import Cocoa import FlutterMacOS // Entry point Flutter calls into via RegisterGeneratedPlugins - this is what // makes CursorLock and the eyedropper "just work" for any app that depends // on garage_ui, without that app having to hand-wire the channels itself in // its own MainFlutterWindow.swift. Used to be duplicated per-app, which is // exactly how it silently went stale (renamed channel on one side, not the // other) and why a brand new app (no Runner wiring at all) got a // MissingPluginException out of the box. public class GarageUiPlugin: NSObject, FlutterPlugin { public static func register(with registrar: FlutterPluginRegistrar) { let instance = GarageUiPlugin() let cursorLockChannel = FlutterMethodChannel( name: "garage/cursor_lock", binaryMessenger: registrar.messenger ) // CursorLock needs to hang on to the channel itself so it can push // scrubDelta calls back to dart - see its own header for why a plain // local var here isnt enough (it needs a home that outlives this fn) CursorLock.shared.attach(channel: cursorLockChannel) registrar.addMethodCallDelegate(instance, channel: cursorLockChannel) let eyedropperChannel = FlutterMethodChannel( name: "garage/eyedropper", binaryMessenger: registrar.messenger ) registrar.addMethodCallDelegate(instance, channel: eyedropperChannel) } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { case "lock": CursorLock.shared.lock() result(nil) case "unlock": CursorLock.shared.unlock() result(nil) case "isAvailable": if #available(macOS 10.15, *) { result(true) } else { result(false) } case "pick": if #available(macOS 10.15, *) { ScreenColorSampler.shared.show(result: result) } else { // dart reads nil as a cancel, which is close enough - it only ever // asks for a pick after isAvailable said yes anyway result(nil) } default: result(FlutterMethodNotImplemented) } } }