pulsar/macos/Runner/AppDelegate.swift
2026-04-30 04:39:20 +01:00

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
}
}