私は最近、マルチメディアキーをキャプチャするquodlibetの拡張機能をコーディングしました(quodlibet自体に吸収されたため)。セットアップにも同じプロセスが適用されます。
これを実現するために、QuartzCGEventTapCreate
フックとイベントループ、およびCocoaAppKitフレームワークを使用してキーコードを解読しました。
次のコードは、グローバルキーの押下が渡される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
1つ以上のイベントタイプを使用)。たとえば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)
NSEvent
Macマルチメディアキーで見つけたすべての情報がそのクラスを参照していたため、Quartzイベントをに変換しました。
原則として、AppKit APIでも同じことを実現できますが、PythonアプリケーションはMacアプリケーション(Dockにアイコンなどで表示されます)として扱われますが、これは完全にバックグラウンドで保持する必要があります。