我最近编写了一个quodlibet的扩展来捕获多媒体键(因为被 quodlibet 本身所吸引);对于您的设置,同样的过程适用。
我使用 QuartzCGEventTapCreate
钩子和事件循环以及 Cocoa AppKit 框架来破译关键代码来实现这一点。
以下代码注册了一个传递全局按键的python回调,并启动事件循环:
import Quartz
from AppKit import NSKeyUp, NSSystemDefined, NSEvent
# Set up a tap, with type of tap, location, options and event mask
tap = Quartz.CGEventTapCreate(
Quartz.kCGSessionEventTap, # Session level is enough for our needs
Quartz.kCGHeadInsertEventTap, # Insert wherever, we do not filter
Quartz.kCGEventTapOptionListenOnly, # Listening is enough
Quartz.CGEventMaskBit(NSSystemDefined), # NSSystemDefined for media keys
keyboardTapCallback,
None
)
runLoopSource = Quartz.CFMachPortCreateRunLoopSource(None, tap, 0)
Quartz.CFRunLoopAddSource(
Quartz.CFRunLoopGetCurrent(),
runLoopSource,
Quartz.kCFRunLoopDefaultMode
)
# Enable the tap
Quartz.CGEventTapEnable(tap, True)
# and run! This won't return until we exit or are terminated.
Quartz.CFRunLoopRun()
我只为系统定义的键(媒体键)定义了一个水龙头;您必须指定不同的事件掩码(CGEventMaskBit
具有一个或多个事件类型);例如Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp)
按键事件。
回调应该具有以下签名(它实现CGEventTapCallBack
了 Quartz API 中的方法:
def keyboardTapCallback(proxy, type_, event, refcon):
# Convert the Quartz CGEvent into something more useful
keyEvent = NSEvent.eventWithCGEvent_(event)
我将 Quartz 事件转换为NSEvent
,因为我可以在 Mac 多媒体键上找到的所有信息都与该类有关。
原则上,您也可以使用 AppKit API 实现相同的功能,但是您的 Python 应用程序被视为 Mac 应用程序(在 Dock 中可见,带有图标和所有内容),而我希望它完全保留在后台。