【问题标题】:What is the right API to use to remap keys in OSX?在 OSX 中重新映射键的正确 API 是什么?
【发布时间】:2020-07-27 07:06:30
【问题描述】:

我正在研究用于 Parallels 开发的 OSX 键盘重新映射器 Karabiner。根据this issue 的说法,最好通过向 Apple 提交错误来解决此问题。

创建此类功能的其他受支持的 API(如果有)是什么?

【问题讨论】:

    标签: macos nstouchbar


    【解决方案1】:

    pkambpkamb 在 OP 链接到的 github 问题上(自他发布后添加),Apple technote TN2450 记录了正确的 API:

    IOKit HID API 可用于密钥重新映射。用户将 提供 HID 事件系统将执行的键重新映射字典 应用于键盘。
    清单 3:使用 IOKit HID 的键重映射 蜜蜂。 // 使用 Xcode 8.2.1 编译

    #import <Foundation/Foundation.h>
    #import <IOKit/hidsystem/IOHIDEventSystemClient.h>
    #import <IOKit/hidsystem/IOHIDServiceClient.h>
    #import <IOKit/hid/IOHIDUsageTables.h>
    
    int main(int argc, char *argv[])
    {
        IOHIDEventSystemClientRef system;
        CFArrayRef services;
    
        uint64_t aKey = 0x700000004;
        uint64_t bKey = 0x700000005;
    
        NSArray *map = @[
                         @{@kIOHIDKeyboardModifierMappingSrcKey:@(aKey),
                            @kIOHIDKeyboardModifierMappingDstKey:@(bKey)},
                         @{@kIOHIDKeyboardModifierMappingSrcKey:@(bKey),
                            @kIOHIDKeyboardModifierMappingDstKey:@(aKey)},
                         ];
    
        system = IOHIDEventSystemClientCreateSimpleClient(kCFAllocatorDefault);
        services = IOHIDEventSystemClientCopyServices(system);
        for(CFIndex i = 0; i < CFArrayGetCount(services); i++) {
            IOHIDServiceClientRef service = (IOHIDServiceClientRef)CFArrayGetValueAtIndex(services, i);
            if(IOHIDServiceClientConformsTo(service, kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard)) {
                IOHIDServiceClientSetProperty(service, CFSTR(kIOHIDUserKeyUsageMapKey), (CFArrayRef)map);
            }
        }
    
        CFRelease(services);
        CFRelease(system);
    
        return 0;
    }
    

    示例:
    如果您尝试在外部 USB 键盘上重新映射命令/选项/控制键,请查看 IOHIDUsageTables.h 中定义的 enum。例如,可以使用此映射重新映射 Z-88 键盘以匹配 MacBookPro 上的按键布局:

    NSArray *remap = @[
      @{@kIOHIDKeyboardModifierMappingSrcKey:@(0x7000000E3),
        @kIOHIDKeyboardModifierMappingDstKey:@(0x7000000E2)},
      @{@kIOHIDKeyboardModifierMappingSrcKey:@(0x7000000E2),
        @kIOHIDKeyboardModifierMappingDstKey:@(0x7000000E3)},
      @{@kIOHIDKeyboardModifierMappingSrcKey:@(0x7000000E6),
        @kIOHIDKeyboardModifierMappingDstKey:@(0x7000000E7)},
      @{@kIOHIDKeyboardModifierMappingSrcKey:@(0x700000065),
        @kIOHIDKeyboardModifierMappingDstKey:@(0x7000000E6)}
    ];
    
    • LeftGUI (E3) → LeftAlt (E2)
    • LeftAlt (E2) → LeftGUI (E3)
    • RightAlt (E6) → RightGUI (E7)
    • 应用程序 (65) → RightAlt (E6)

    要撤消映射,请将相同的键映射回其原始值。使用上面的例子:

    NSArray *unmap = @[
      @{@kIOHIDKeyboardModifierMappingSrcKey:@(0x7000000E3),
        @kIOHIDKeyboardModifierMappingDstKey:@(0x7000000E3)},
      @{@kIOHIDKeyboardModifierMappingSrcKey:@(0x7000000E2),
        @kIOHIDKeyboardModifierMappingDstKey:@(0x7000000E2)},
      @{@kIOHIDKeyboardModifierMappingSrcKey:@(0x7000000E6),
        @kIOHIDKeyboardModifierMappingDstKey:@(0x7000000E6)},
      @{@kIOHIDKeyboardModifierMappingSrcKey:@(0x700000065),
        @kIOHIDKeyboardModifierMappingDstKey:@(0x700000065)}
    ];
    

    【讨论】:

      【解决方案2】:

      Karabiner-Elements 尽管文档和用户界面略显简陋,但它还是可靠且通用的,对于正在进行的工作来说是可以原谅的。有许多有用的示例,例如this one,它需要专用工具和 Karabiner 错误日志来生成棘手的 JSON 规则。任何键都可以同时是修饰键和常规键、运行程序等。 GitHub 上的公共域。

      【讨论】:

      • 这似乎不是对应该使用什么 API 在 macOS 上进行密钥重新映射的问题的答案。
      • 也许最好的答案是不要重新发明 Karabiner,因为 Karabiner-Elements 解决了导致问题的问题。
      • OP 专门要求提供 Karabiner 的替代品。诚然,在大约 3 年的中断之后,开发可能会再次进行,因此可能值得重新评估 Karabiner 作为一种选择,但这仍然不能回答问题。
      • Karabiner-Elements 是 Karabiner 的替代品。
      猜你喜欢
      • 1970-01-01
      • 2019-11-26
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 2017-10-30
      • 1970-01-01
      • 2021-03-02
      • 2015-08-13
      相关资源
      最近更新 更多