对于非为 macOS 设计的蓝牙键盘,需要将 command ⌘ / windows 键与 option ⌥ / Alt 键调换;此外对于 emacs 快捷键,将 caps lock 映射为 control 键则可以极大方便使用。对于蓝牙 4.0 及以上的蓝牙键盘(如 MX Keys / CIY 键盘),在 macOS 中如被识别为 Bluetooth Low Energy 设备,则系统设置中的的修饰键(modifier keys)将无法选择该设备,从而无法进行键位因为修改。本文介绍使用 hidutil
进行键位映射,并使用 launchctl
实现设备连接后自动修改映射表。
hidutil (Human Interface Device) 工具
hidutil 命令行工具可以对 macOS 10.12 以上系统键位进行映射,通过 property
进一步筛选设备后进行修改,例如:
hidutil property --matching '{"Product": "YOUR_DEVICE_NAME"}' \
--set '{"UserKeyMapping": [{"HIDKeyboardModifierMappingSrc":0x700000039,
"HIDKeyboardModifierMappingDst":0x7000000e0}]}'
将 0x700000039
(caps lock) 映射为 0x7000000e0
(左 control),同时仅对 YOUR_DEVICE_NAME 设备生效,对其他设备例如 MacBook 内置键盘没有影响。其中 YOUR_DEVICE_NAME 为设备名,可以使用 hidutil list
进行查询。
该命令可以多次执行,但效果不会叠加,即每次修改仅对一个按键有效。如果有多个按键需要映射,可以填充多个按键映射的键值,例如:
hidutil property --matching '{"Product": "YOUR_DEVICE_NAME"}' \
--set '{"UserKeyMapping": [{"HIDKeyboardModifierMappingSrc":0x7000000e2,
"HIDKeyboardModifierMappingDst":0x7000000e3},
{"HIDKeyboardModifierMappingSrc":0x7000000e6,
"HIDKeyboardModifierMappingDst":0x7000000e7},
{"HIDKeyboardModifierMappingSrc":0x7000000e3,
"HIDKeyboardModifierMappingDst":0x7000000e2}]}'
以上命令可以将 YOUR_DEVICE_NAME 设备的左右 command 和 option 键位的对调。
同时可以对系统偏好设置中修饰键设置不能实现的映射进行修改,例如将 F10、F11 与 F12 映射为静音、音量减与音量加:
{"HIDKeyboardModifierMappingSrc":0x700000044,
"HIDKeyboardModifierMappingDst":0xc000000ea},
{"HIDKeyboardModifierMappingSrc":0x700000045,
"HIDKeyboardModifierMappingDst":0xc000000e9},
{"HIDKeyboardModifierMappingSrc":0x700000043,
"HIDKeyboardModifierMappingDst":0xc000000e2},
另外 Windows 键盘常见的按键 manu 菜单键,在macOS中不能被准确识别,其键位值为 0x700000065
,可以通过添加以下键值将 manu 键映射为右 option:
{"HIDKeyboardModifierMappingSrc":0x700000065,
"HIDKeyboardModifierMappingDst":0x7000000e6},
更多键位查询可以参考hidutil官方手册,或者第三方网站 https://hidutil-generator.netlify.app/
可将命令保存为 .sh
文件,方便多次执行,或者使用自动操作 Automator 中新建应用程序并添加运行shell脚本方便多次使用。
设备连接自动执行键位映射脚本
以上 hidutil 命令在设备断开连接后重新连接需要重新设置,并且在系统重启后也需要再运行进行设定,并不是非常高雅与方便。因此可以借助 launchctl
服务管理对蓝牙列表进行监看,如果有新增特定的设备即执行脚本进行自动切换。
首先我们将需要切换的设备的命令写入脚本 ~/.keysModifer.sh
:
#!/bin/bash
connectedyesorno="$(system_profiler SPBluetoothDataType | awk '/YOUR_DEVICE_NAME/{f=1}/Connected:/ && f{print $2; exit}')"
if [ "$connectedyesorno" == "Yes" ]
then
hidutil property --matching '{"Product": "YOUR_DEVICE_NAME"}' \
--set '{"UserKeyMapping": [{"HIDKeyboardModifierMappingSrc":0x700000039,
"HIDKeyboardModifierMappingDst":0x7000000e0}]}'
elif [ "$connectedyesorno" == "No" ]
then
echo "Not connected..."
else
echo "ERROR"
fi
以上例子中映射 YOUR_DEVICE_NAME 设备 caps lock 到 control。其中两处的YOUR_DEVICE_NAME
设备名称需要使用hidutil list
进行查询后修改,同时注意特殊符号的转义。届时可以尝试执行 sh ~/.keysModifer.sh
查看结果,注意要在设备连接时进行尝试。
之后在 ~/Library/LaunchAgents
新建 com.my.keysModifier.plist
文件,加入以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.my.keysModifier</string>
<key>ProgramArguments</key>
<array>
<string>/bin/sh</string>
<string>/Users/YOUR_USERNAME/.keyModi.sh</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/com.apple.Bluetooth.plist</string>
</array>
</dict>
</plist>
注意替换 YOUR_USERNAME
为用户名。之后使用
launchctl load ~/Library/LaunchAgents/com.my.keysModifier.plist
启动服务,当/Library/Preferences/com.apple.Bluetooth.plist
文件变化时执行~/.keysModifer.sh
脚本对键位映射进行修改。
停止服务可以使用以下命令:
launchctl unload ~/Library/LaunchAgents/com.my.keysModifier.plist
需要注意的是,对 plish 文件修改后需要关闭服务后重新启动,对 sh 文件修改后则无需特殊修改。
使用以下命令可以进一步删除上文生成的两个文件,恢复原始状态:
rm ~/Library/LaunchAgents/com.my.keysModifier.plist
rm ~/.keysModifer.sh
另外如果有多个设备需要判断并修改,可以在.keysModifer.sh
文件中使用多个 connectedyesorno
变量判断条件对不同设备的连接状态判断后进行映射修改。