Python Mac OS X的系统范围快捷方式

Python Mac OS X的系统范围快捷方式,python,objective-c,macos,qt,pyqt,Python,Objective C,Macos,Qt,Pyqt,所以我被要求将一些内部助手应用程序移植到MacOSX10.7 这一切都很好,因为依赖于平台的代码是最少的,但是一个应用程序需要一个系统范围的功能快捷方式(即功能),我找不到任何关于如何在Mac上实现这一点的文档 该程序使用PyQt gui和Python3.2。windows对应的代码基本上是: def register_hotkey(self): hwnd = int(self.winId()) modifiers, key = self._get_hotkey() us

所以我被要求将一些内部助手应用程序移植到MacOSX10.7

这一切都很好,因为依赖于平台的代码是最少的,但是一个应用程序需要一个系统范围的功能快捷方式(即功能),我找不到任何关于如何在Mac上实现这一点的文档

该程序使用PyQt gui和Python3.2。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解决方案也很受欢迎。

我发现,使用google的强大功能,可以注册Mac OS X的全局热键

您需要添加
Carbon
框架,并且在将Objective-C self指针传递到C函数时,可能需要为
ARC
添加桥接cast

至少,您还需要:

#import <Carbon/Carbon.h>
#导入
可以看到按键代码。

我最近编写了一个用于捕获多媒体按键的代码(因为它被quodlibet本身所吸收);对于您的设置,同样的过程也适用

我使用Quartz和event循环以及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()
我只为系统定义的键(媒体键)定义了一个点击;您必须指定一个不同的事件掩码(
cgreventmaskbit
带有一个或多个);e、 g.
Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp)
用于按键启动事件

回调应具有以下签名(它实现:

我把Quartz事件转换成了一个事件,因为我在Mac多媒体键上找到的所有信息都是关于那个类的


原则上,您也可以使用AppKit API实现同样的功能,但是您的Python应用程序将被视为Mac应用程序(在Dock中可以看到图标和所有内容),而我想把它全部放在后台。

为什么从来没有人提到hammerspoon,它支持自定义全局系统快捷方式,可以调用shell命令或启动Safari、PHOTOSHOP等UI应用程序

下面是我编写的一个示例,演示了如何使用全局热键调用shell函数。

使用hs.execute执行shell命令,可以是非交互式的,也可以是交互式的

hs.hotkey.bind({"cmd", "alt", "ctrl"}, "P", function()
  local output = hs.execute("toggleProxy", true)
  hs.alert.show(output)
end)
或 使用hs.application.launchOrFocus启动应用程序
hs.application.launchOrFocus(“Safari”)

谢谢,看起来正是我需要的。我让pyobjc为Python3编译(比预期的稍微麻烦),但当运行代码时,它告诉我
AttributeError:“module”对象没有属性“CGEventTapCreate”
。pyobjc应该与python3一起工作,那么我是缺少了什么东西还是API没有完全移植?@Voo:对不起,不知道;我只使用了python 2.7和pyobjc。早上对问题进行了一点调试,并修复了它。需要离开是:python3和pyobjc确实不值得推荐,但可以让它发挥作用。当然,这比学习cocoa框架或将应用程序向后移植到python2要省力。再次感谢您的帮助。通过将您的SO昵称与您提供的URL进行比较,可以看出这是指向您自己的一个项目的链接。您应该请编辑您的答案以澄清这一点,否则可能会被标记为垃圾邮件。请参阅此处:
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "P", function()
  local output = hs.execute("toggleProxy", true)
  hs.alert.show(output)
end)