有没有人设法使此功能在Swift中工作?
苹果文档:https : //developer.apple.com/library/prerelease/mac/documentation/Carbon/Reference/QuartzEventServicesRef/index.html#//apple_ref/c/func/CGEventTapCreate
以下是CGEventTapCallBack的定义方式:
typealias CGEventTapCallBack = CFunctionPointer<((CGEventTapProxy, CGEventType, CGEvent!, UnsafeMutablePointer<Void>) -> Unmanaged<CGEvent>!)>
这是我编写块的方式:
let eventTapCallBackBlock : @objc_block (CGEventTapProxy, CGEventType, CGEventRef, UnsafeMutablePointer<Void>) -> CGEventRef = { (eventTapProxy: CGEventTapProxy, eventType: CGEventType, event: CGEventRef, refcon: UnsafeMutablePointer<Void>) in return event }
然后我用回调参数调用了CGEventTapCreate unsafeBitCast(eventTapCallBackBlock, CGEventTapCallBack.self)
unsafeBitCast(eventTapCallBackBlock, CGEventTapCallBack.self)
我得到了有效的CFMachPortRef退款,但是在运行时,我在第一个事件中遇到了访问冲突异常。它将“似乎”以其当前发布状态迅速接近一个解决方案。
CFMachPortRef
使用Xcode版本6.4
的callback参数CGEventTapCreate()是C函数指针,在 Swift 1.x中 ,无法通过Swift函数参数调用它。
callback
CGEventTapCreate()
但是,在 Swift 2 (Xcode 7)中,可以使用闭包或全局函数来调用带有函数指针参数的C函数(但要注意,闭包不得捕获其任何本地上下文)。
例如,以下是 对Swift 的接收,筛选和修改按键和释放的完整翻译 :
import Foundation func myCGEventCallback(proxy : CGEventTapProxy, type : CGEventType, event : CGEvent, refcon : UnsafeMutablePointer<Void>) -> Unmanaged<CGEvent>? { if [.KeyDown , .KeyUp].contains(type) { var keyCode = CGEventGetIntegerValueField(event, .KeyboardEventKeycode) if keyCode == 0 { keyCode = 6 } else if keyCode == 6 { keyCode = 0 } CGEventSetIntegerValueField(event, .KeyboardEventKeycode, keyCode) } return Unmanaged.passRetained(event) } let eventMask = (1 << CGEventType.KeyDown.rawValue) | (1 << CGEventType.KeyUp.rawValue) guard let eventTap = CGEventTapCreate(.CGSessionEventTap, .HeadInsertEventTap, .Default, CGEventMask(eventMask), myCGEventCallback, nil) else { print("failed to create event tap") exit(1) } let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0) CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes) CGEventTapEnable(eventTap, true) CFRunLoopRun()
Swift 3 更新 :
import Foundation func myCGEventCallback(proxy: CGEventTapProxy, type: CGEventType, event: CGEvent, refcon: UnsafeMutableRawPointer?) -> Unmanaged<CGEvent>? { if [.keyDown , .keyUp].contains(type) { var keyCode = event.getIntegerValueField(.keyboardEventKeycode) if keyCode == 0 { keyCode = 6 } else if keyCode == 6 { keyCode = 0 } event.setIntegerValueField(.keyboardEventKeycode, value: keyCode) } return Unmanaged.passRetained(event) } let eventMask = (1 << CGEventType.keyDown.rawValue) | (1 << CGEventType.keyUp.rawValue) guard let eventTap = CGEvent.tapCreate(tap: .cgSessionEventTap, place: .headInsertEventTap, options: .defaultTap, eventsOfInterest: CGEventMask(eventMask), callback: myCGEventCallback, userInfo: nil) else { print("failed to create event tap") exit(1) } let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0) CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes) CGEvent.tapEnable(tap: eventTap, enable: true) CFRunLoopRun()