Mac OS X 系统范围的快捷方式 [英] system wide shortcut for Mac OS X

查看:21
本文介绍了Mac OS X 系统范围的快捷方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我被要求将一些内部帮助应用程序移植到 Mac OS X 10.7.

So I was asked to port some internal helper applications to Mac OS X 10.7.

工作得很好,因为平台相关的代码无论如何都是最少的,但是一个应用程序需要一个系统范围的快捷方式才能运行(即 RegisterHotkey 功能),但我找不到有关如何在 Mac 上执行此操作的任何文档.

Works all quite welll as the platform dependent code is minimal anyhow, but one application needs a system wide shortcut to function (i.e. RegisterHotkey functionality) and I can't find any documentation on how I'd do this on a Mac.

该程序使用 PyQt gui 和 Python 3.2.而windows对应的代码基本上是:

The program is using a PyQt gui with Python 3.2. and the corresponding code for windows is basically:

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 解决方案.

Note that I don't need a python variant, I can easily write a simple c extension - so C/objective-c solutions are welcome as well.

推荐答案

我最近编写了一个 扩展quodlibet 捕获多媒体密钥(因为被吸收进入 quodlibet 本身);对于您的设置,同样的过程适用.

I recently coded up an extension to quodlibet capturing multimedia keys (since absorbed into quodlibet itself); for your setup the same process applies.

我使用了 Quartz CGEventTapCreate 钩子 和事件循环,以及 Cocoa AppKit 框架来解密实现这一点的关键代码.

I used the Quartz CGEventTapCreate hook and event loop, and the Cocoa AppKit framework to decipher key codes to achieve this.

以下代码注册了一个python回调,该回调通过全局按键按下,并启动事件循环:

The following code registers a python callback which is passed global key presses, and starts the event loop:

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) 按键事件.

I defined a tap for system defined keys only (media keys); you'll have to specify a different event mask (CGEventMaskBit with one or more Event Types); e.g. Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp) for key up events.

回调应该具有以下签名(它实现了CGEventTapCallBack 来自 Quartz API 的方法:

The callback should have the following signature (it implements the 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 多媒体键上能找到的所有信息都是指那个类.

I converted the Quartz event into a NSEvent, because all the information I could find on Mac multimedia keys was referring to that class.

原则上,您也可以使用 AppKit API 实现相同的功能,但是您的 Python 应用程序被视为 Mac 应用程序(在 Dock 中可见,带有图标和所有内容),而我希望将其保留在后台一共.

In principle you can achieve the same thing with the AppKit APIs too, but then your Python application is treated as a Mac Application (visible in the Dock with an icon and everything), while I wanted this to be kept in the background altogether.

这篇关于Mac OS X 系统范围的快捷方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆