微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

你如何在Swift中使用CGEventTapCreate?

有没有人设法让这个功能Swift中工作?

这是去年的参考SO帖子:Using CGEventTapCreate Trouble with parameters in Swift

Apple Doc: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,CGEventRef,UnsafeMutablePointer<Void>) -> CGEventRef =
{ (eventTapProxy: CGEventTapProxy,eventType: CGEventType,event: CGEventRef,refcon: UnsafeMutablePointer<Void>) in
  return event
}

然后我用回调参数调用CGEventTapCreate,如unsafeBitCast(eventTapCallBackBlock,CGEventTapCallBack.self)

我得到一个有效的CFMachPortRef,但在运行时我在第一个事件上遇到访问冲突异常.它似乎“似乎”我在当前发布状态下接近迅速解决方案.

使用Xcode版本6.4

解决方法

CGEventTapCreate()的回调参数是一个C函数指针,
在Swift 1.x中,不可能使用Swift函数参数调用它.

但是,在Swift 2(Xcode 7)中,C函数接受函数指针参数
可以使用闭包或全局函数调用(具有限制
闭包不得捕获任何本地语境).

作为一个例子,这里是一个完整的翻译
Receiving,Filtering,and Modifying Key Presses and Releases
到斯威夫特:

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,.commonModes)
CGEvent.tapEnable(tap: eventTap,enable: true)
CFRunLoopRun()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐