如何在OSX上挂钩/重新映射任意键盘事件?

时间:2015-05-18 16:16:11

标签: macos hook keyboard-events key-bindings

我想映射:

  • CAPS-LOCK Fn
  • Fn 至Left-MOUSE
  • LSHIFT + 3 to
  • RSHIFT + 3 到别的地方

我已经详尽地搜索了任何可以完全自由地重新映射键盘输入的工具,但却无法找到。 (Windows有AutoHotkey)。

我打算编写一个解析配置文件的工具。

但是如何实际挖掘并做到这一点?

解决这个问题需要彻底了解通过操作系统进行击键的过程,以便在适当的时候进行拦截。

我认为我需要在低级别处使用该事件,它仍然是虚拟密钥代码,然后提供我自己的自定义映射系统并在系统中进一步注入适当的事件。

但是在哪里(以及如何)?

编辑:我在下面的答案中详述了我的研究结果(可能应该在某个时候将其迁回到问题中)。

2 个答案:

答案 0 :(得分:17)

我正在制作此社区维基,欢迎您加以改进。

我问过的子问题:

我可以截取中间层底部的几乎所有keydown / keyup事件。除了电源,以及从ON到OFF转换时的CAPSLOCK键控。

非常讨厌!

在底层工作,我可以获得除PowerKey之外的所有键。

如果不是因为CapsLock的成功率为75%,我会有一个很好的解决方案。令人烦恼的是,在如此有用的位置处理密钥会大大增加所需的复杂性。

我找到了DDHidLib,目前正在查看它是否能解决这个问题。

研究

谷歌搜索" keyEventWithType CGEventTapCreate"这似乎是一个好主意,因为这些是开发事件和重新发布它的必要因素。

耶! Modify keyDown output - 该代码编译,并通过微调(CGEventMaskBit( kCGEventKeyDown ) | CGEventMaskBit( kCGEventFlagsChanged ),)我也可以获取修改键。我为LSHIFT和RSHIFT获得了不同的密钥代码。辉煌!

上述问题:

  • 点击kCGEventKeyDown适用于某些功能键但不适用于其他功能键。看起来苹果只是重载某些键,而超载的键似乎陷入了较低的水平。
  • 电源/弹出键无法被捕获。
  • 我没有看到任何方法来消除键击来自哪个设备的歧义。

How to tap (hook) F7 through F12 and Power/Eject on a MacBook keyboard

http://blog.tklee.org/2008/09/modifiers-across-keyboards.html
- > http://forums.macrumors.com/showthread.php?t=778484
- > https://github.com/maravillas/dual-keyboards

https://github.com/pkamb/PowerKey可能会提供一些见解 - > https://github.com/pkamb/PowerKey/blob/master/PowerKey/PKPowerKeyEventListener.m
- > Apple Keyboard Media Key Event Handling -- Rogue Amoeba
...... system wide shortcut for Mac OS X
- > http://snippets.aktagon.com/snippets/361-registering-global-hot-keys-with-cocoa-and-objective-c

另一个问题是:LSHIFT-down RSHIFT-down& up LSHIFT-up。 RSHIFT事件不会被抓住。

看起来我需要深入了解IOKit

Using IOHIDManager to Get Modifier Key Events
- > https://github.com/candera/khordr/blob/master/src/c/keygrab/hid-scratch.c

kEventRawKeyDown in:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/
Developer/SDKs/MacOSX10.10.sdk/System/Library/
Frameworks//Carbon.framework/Frameworks/HIToolbox.framework/
Headers/CarbonEvents.h

资源

3层:

  • Cocoa / AppKit是一个更高级别的包装器
  • Quartz从IOKit获取事件将它们路由到应用程序
    注意:NSEvent是基于Quartz Event

  • 构建的
  • IOKit - 与硬件对话

3-tier

Top Tier(Cocoa / AppKit)

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html - 这个文件是必看的,并显示了上面的基本3层架构pic。但是,它似乎只关注顶层(Cocoa / AppKit)。

http://www.hcs.harvard.edu/~jrus/Site/Cocoa%20Text%20System.html< - 本文向您展示了3个更高级别的OSX配置文件,让您编写自己的映射脚本。记录在案here

^ KeyBindingsEditor可让您进行上述修改。

中间层(石英)

QuartzEventServicesRef

NSEvent - 具体为Creating Events

此级别的几个工作代码示例。但是,它们都执行接收一个虚拟密钥代码并发出另一个虚拟密钥代码的相同基本技巧。因此,您可以使用此技术来交换' a'和' z'。

Intercept keyboard input in OSX - 导致Quartz Event Taps

Modify NSEvent to send a different key than the one that was pressed - Dave De Long提供了一个工作示例,也使用了QET。

https://gist.github.com/wewearglasses/8313195< - " OSX的全局键盘钩子" - 使用QET的另一个简短工作演示。

Ukelele允许您选择与特定键或Modifier +键关联的Unicode。不允许重新映射修饰符,也不会消除右移键等的左移。

Keyboard input on OSX - 在NSEvent中回答addGlobalMonitorForEventsMatchingMask(在AppKit中)

基础层(IOKit)

IOKitFundamentals< - 还有IOKit(" I / O Kit中的中断处理......两种类型的事件触发中断:...异步事件,例如键盘按下&#34 ;)

https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Other_APIs/AH_Other_APIs.html

How can Mac OS X games receive low-level keyboard input events?< - 游戏玩家对此感兴趣!

http://phrack.org/issues/66/16.html#article - 有时黑客最清楚地表达事物,还没有读过这个。似乎再次IOKit。

更多链接......

How do you implement global keyboard hooks in Mac OS X?< - 链接到文章。

OSX: Detect system-wide keyDown events?< - 稍微OT,因为这与全局监控有关,即只读。

http://www.codeitive.com/7QHSeVjPWq/where-can-i-find-kcgkeyboardeventkeycode-list-of-key-codes-for-cyrillic-language.html

答案 1 :(得分:1)

你有没有检查过Karabiner(它做了你想做的所有......直到OSX 10.11 .. MacOS 10.12改变了键盘驱动程序模型,作者 - 主要是Tekezo-仍在重写Karabiner以考虑到新模型 - 这是2017年2月的一部分) Karabiner是开源的,您可以从Github下载代码并随之旋转。

作为重写的一部分,他们发布了适用于10.12 Sierra的Karabiner元素,但还不能完成karabiner所做的一切。

Karabiner非常强大,我在10.12非常想念