2012-07-05 57 views
2

因此我被要求将一些内部帮助应用程序移植到Mac OS X 10.7。适用于Mac OS X的系统范围快捷方式

工作都非常好,因为平台相关的代码是最小的无论如何,但一个应用程序需要一个系统范围的快捷方式功能(即RegisterHotkey功能),我找不到任何文档,我怎么会在Mac上做到这一点。

该程序在Python 3.2中使用了PyQt gui。和Windows对应的代码基本上是:

def register_hotkey(self): 
    hwnd = int(self.winId()) 
    modifiers, key = self._get_hotkey() 
    user32.RegisterHotKey(hwnd, self._MESSAGE_ID, modifiers, key) 

,然后接收热键事件:

def winEvent(self, msg): 
    if msg.message == w32.WM_HOTKEY: 
     self.handle_hotkey() 
     return True, id(msg) 
    return False, id(msg) 

请注意,我并不需要一个Python变种,我可以很容易地编写一个简单的C扩展 - 所以C/objective-c解决方案也是受欢迎的。

回答

8

我最近编码了一个extensionquodlibet捕获多媒体密钥(因为吸收到quodlibet本身);为您的设置适用相同的过程。

我使用Quartz CGEventTapCreate hook和事件循环,并使用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与一个或多个Event Types);例如Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp)关键事件。

回调应具有以下特征(它实现了CGEventTapCallBack method from the Quartz API

def keyboardTapCallback(proxy, type_, event, refcon): 
    # Convert the Quartz CGEvent into something more useful 
    keyEvent = NSEvent.eventWithCGEvent_(event) 

我转换的石英事件为NSEvent,因为所有我能找到在Mac上的多媒体按键信息指的是那类。

原则上你也可以用AppKit API实现同样的事情,但是你的Python应用程序被当作Mac应用程序(在Dock中可以看到一个图标和所有东西),而我希望它保存在共有背景

+0

谢谢,看起来正是我所需要的。我得到pyobjc为Python3进行编译(稍微比预期更麻烦),但是当运行代码时它告诉我'AttributeError:'模块'对象没有属性'CGEventTapCreate'。 pyobjc应该与python3一起工作,所以我错过了一些东西,或者API只是没有完全移植? – Voo 2012-07-06 00:57:39

+0

@Voo:对不起,不知道;我只使用python 2.7和pyobjc。 – 2012-07-06 05:49:26

+2

早上调试了一下这个问题并修复了它。结论是:python3和pyobjc真的不被推荐,但可以让它工作。这肯定比学习可可框架或将应用程序反向移植到python2的工作要少。再次感谢您的帮助。 – Voo 2012-07-06 11:28:47