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

时间:2012-07-05 15:41:57

标签: python objective-c macos qt pyqt

因此我被要求将一些内部帮助应用程序移植到Mac OS X 10.7。

因为平台相关代码无论如何都很小,所以非常有用,但是一个应用程序需要一个系统范围的快捷方式来运行(即RegisterHotkey功能)而且我找不到任何关于我如何执行此操作的文档在Mac上。

该程序使用PyQt gui和Python 3.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解决方案也是受欢迎的。

3 个答案:

答案 0 :(得分: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()

我为系统定义的键定义了一个tap(媒体键);你必须指定一个不同的事件掩码(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)

我将Quartz事件转换为NSEvent,因为我在Mac多媒体键上找到的所有信息都是指那个类。

原则上你也可以用AppKit API实现同样的功能,但是你的Python应用程序被视为Mac应用程序(在Dock中可以看到带有图标和所有内容),而我希望将它保存在后台共

答案 1 :(得分:1)

利用谷歌的力量,我找到了this snippet of code,它允许注册Mac OS X的全局热键

在将Objective-C指针传递给C函数时,您需要添加Carbon框架,并且可能是ARC的桥接转换。

至少,您还需要:

#import <Carbon/Carbon.h>

可以看到密码代码on this page explaining the virtual key codes

答案 2 :(得分:0)

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

以下是我写的一个示例,演示如何使用全局热键调用shell函数。 https://gist.github.com/BigSully/0e59ab97f148bc167ea19dbd42ebef4b

使用 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”)