84 lines
2.8 KiB
Swift
84 lines
2.8 KiB
Swift
import Cocoa
|
|
import FlutterMacOS
|
|
import CoreGraphics
|
|
|
|
@main
|
|
class AppDelegate: FlutterAppDelegate {
|
|
private var inputChannel: FlutterMethodChannel?
|
|
|
|
override func applicationDidFinishLaunching(_ notification: Notification) {
|
|
guard let window = mainFlutterWindow,
|
|
let ctrl = window.contentViewController as? FlutterViewController else { return }
|
|
|
|
inputChannel = FlutterMethodChannel(
|
|
name: "com.pulsar/input",
|
|
binaryMessenger: ctrl.engine.binaryMessenger
|
|
)
|
|
|
|
inputChannel?.setMethodCallHandler { [weak self] call, result in
|
|
if call.method == "injectInput",
|
|
let args = call.arguments as? [String: Any] {
|
|
self?.injectInput(args)
|
|
result(nil)
|
|
} else {
|
|
result(FlutterMethodNotImplemented)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func injectInput(_ ev: [String: Any]) {
|
|
guard let type = ev["type"] as? String else { return }
|
|
let screen = NSScreen.main?.frame ?? CGRect(x: 0, y: 0, width: 1920, height: 1080)
|
|
|
|
switch type {
|
|
case "move":
|
|
let nx = ev["x"] as? Double ?? 0
|
|
let ny = ev["y"] as? Double ?? 0
|
|
// CoreGraphics origin is top-left on screen, NSScreen origin is bottom-left
|
|
let px = CGFloat(nx) * screen.width
|
|
let py = CGFloat(ny) * screen.height
|
|
let pt = CGPoint(x: px, y: py)
|
|
CGEvent(mouseEventSource: nil, mouseType: .mouseMoved, mouseCursorPosition: pt, mouseButton: .left)?
|
|
.post(tap: .cghidEventTap)
|
|
|
|
case "click":
|
|
let nx = ev["x"] as? Double ?? 0
|
|
let ny = ev["y"] as? Double ?? 0
|
|
let btn = ev["button"] as? Int ?? 0
|
|
let px = CGFloat(nx) * screen.width
|
|
let py = CGFloat(ny) * screen.height
|
|
let pt = CGPoint(x: px, y: py)
|
|
|
|
let (downType, upType, mouseBtn): (CGEventType, CGEventType, CGMouseButton) =
|
|
btn == 1 ? (.rightMouseDown, .rightMouseUp, .right) : (.leftMouseDown, .leftMouseUp, .left)
|
|
|
|
CGEvent(mouseEventSource: nil, mouseType: downType, mouseCursorPosition: pt, mouseButton: mouseBtn)?
|
|
.post(tap: .cghidEventTap)
|
|
CGEvent(mouseEventSource: nil, mouseType: upType, mouseCursorPosition: pt, mouseButton: mouseBtn)?
|
|
.post(tap: .cghidEventTap)
|
|
|
|
case "keydown":
|
|
if let code = ev["keyCode"] as? Int {
|
|
CGEvent(keyboardEventSource: nil, virtualKey: CGKeyCode(code & 0xFFFF), keyDown: true)?
|
|
.post(tap: .cghidEventTap)
|
|
}
|
|
|
|
case "keyup":
|
|
if let code = ev["keyCode"] as? Int {
|
|
CGEvent(keyboardEventSource: nil, virtualKey: CGKeyCode(code & 0xFFFF), keyDown: false)?
|
|
.post(tap: .cghidEventTap)
|
|
}
|
|
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
|
return true
|
|
}
|
|
|
|
override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
|
|
return true
|
|
}
|
|
}
|