2

在我继续之前,我想在这篇文章的开头说这可能是最骇人听闻、彻头彻尾的邪恶、令人讨厌的话题,所以我不希望答案包含“合法”代码。

在尝试访问 OS X Mountain Lion 用于包含激活听写的热键组合的内部首选项文件时,我遇到了一些制作精美的有符号整数,其中包含在 System Preferences.app 中定义的键码。问题是,我能想到的唯一方法CGEvent是通过并基本上解析给定密钥代码的位掩码,这可能是徒劳无益且令人讨厌的努力。并且因为CGEvent方便地对内部结构 ( __CGEvent) 进行类型定义,所以无法看到它的内部组织(换句话说,我无法malloc()摆脱这种情况)。到目前为止,我所获得的内容显示在下面的代码中:

/***************************************UNSAFE*****************************************************/
//1048584, -1048585 - Two Left CMD presses; 1048576, -1048577 - Two CMD presses; 8388608, -8388609 - Two Fn presses; 1048592, -1048593 - Two Right CMD presses
- (void)forceDictation {

    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"Preferences/com.apple.symbolichotkeys.plist"];
    NSDictionary *dictationPrefs = [NSDictionary dictionaryWithContentsOfFile:path];
    NSDictionary *dictationDict = dictationPrefs[@"AppleSymbolicHotKeys"];
    NSDictionary *keyvalueDict = dictationDict[@"164"];
    NSDictionary *valueDict = keyvalueDict[@"value"];
    NSArray *parameters = valueDict[@"parameters"];
    NSInteger firstCode = [[parameters objectAtIndex:0]longLongValue];
    NSInteger secondCode = [[parameters objectAtIndex:1]longLongValue];
}

任何熟悉 HIToolbox 中的事件位掩码的人都可以看到这些关键代码表示会有多么令人难以置信的帮助,只要它们可以轻松地转换为事件然后发射为蓝色。

4

1 回答 1

7

让我们看看位模式(你会注意到我已经改变了你列出它们的顺序):

2 × ⌘:
 1048576: 00000000000100000000000000000000
-1048577: 11111111111011111111111111111111

2 × left-⌘:
 1048584: 00000000000100000000000000001000
-1048585: 11111111111011111111111111110111

2 × right-⌘:
 1048592: 00000000000100000000000000010000
-1048593: 11111111111011111111111111101111

2 × Fn:
 8388608: 00000000100000000000000000000000
-8388609: 11111111011111111111111111111111

我无法从中看出什么,除了:

  • 假设正值是“真实”值(请参阅我关于为什么有两个以及为什么所有四对是互补的理论的评论),密钥标识符至少高出 20 位(请注意,在我的第一对中顺序,正值正好是2**20),并且至少有 4 位长(2×Fn 是2**23)。
  • 如果设置受到如此限制,则最低五位中的至少两位指定哪个键(左或右)。左似乎是第一个⌘,而右是第二个。如果这部分为零,则任何标识的键都将匹配——例如,左或右⌘。

但我们实际上可能不需要解析这些位。

在我的 MacBook Air 上,运行Key Codes会给我以下输出:

Modifier Change
  Keys:       ⌘
  Key Code:   65535 / 0xffff
  Modifiers:  1048848 / 0x100110

Modifier Change
  Keys:       
  Key Code:   65535 / 0xffff
  Modifiers:  256 / 0x100

Modifier Change
  Keys:       ⌘
  Key Code:   65535 / 0xffff
  Modifiers:  1048840 / 0x100108

Modifier Change
  Keys:       
  Key Code:   65535 / 0xffff
  Modifiers:  256 / 0x100

Modifier Change
  Keys:       
  Key Code:   65535 / 0xffff
  Modifiers:  8388864 / 0x800100

Modifier Change
  Keys:       
  Key Code:   65535 / 0xffff
  Modifiers:  256 / 0x100

其中一些数字看起来非常熟悉,不是吗?

  • 每当我按下 ⌘ 键时,修饰符状态都会更改为 1048000 范围内的某个值。
  • 当我按 Fn 时,修饰符状态变为 8388864。你的是 8388608。

让我们看看 NSEvent.h 中的修饰符掩码:

NSCommandKeyMask            = 1 << 20,
NSFunctionKeyMask           = 1 << 23,

噢!嗨。

这两个,实际上所有的修饰键(我们知道它们)掩码,都在NSDeviceIndependentModifierFlagsMask

NSDeviceIndependentModifierFlagsMask    = 0xffff0000UL

这意味着16 位取决于设备:它们可能因一台机器或一个键盘而异。换句话说,你的低 16 位可能与我的低 16 位不同。

可是等等!还有更多!

如果我们查看 I/O Kit 的 IOLLEvent.h,我们会发现类似于 NSEvent 中的掩码,此外还有:

/* device-dependent (really?) */

#define   NX_DEVICELCTLKEYMASK    0x00000001
#define   NX_DEVICELSHIFTKEYMASK  0x00000002
#define   NX_DEVICERSHIFTKEYMASK  0x00000004
#define   NX_DEVICELCMDKEYMASK    0x00000008
#define   NX_DEVICERCMDKEYMASK    0x00000010
#define   NX_DEVICELALTKEYMASK    0x00000020
#define   NX_DEVICERALTKEYMASK    0x00000040
#define NX_DEVICERCTLKEYMASK  0x00002000

所以,LCMDKEYMASK0b1000RCMDKEYMASK0b10000。这也与您找到的 left-⌘ 和 right-⌘ 值相匹配:left 是NX_COMMANDMASK | NX_DEVICELCMDKEYMASK,而 right 是NX_COMMANDMASK | NX_DEVICERCMDKEYMASK

由此,我可以得出结论:

  • 这些数字不是完整的 CGEvents。
  • 在每一对中,正值是修饰符标志掩码,负值只是它的补码。
  • 您需要生成的事件是修饰符更改事件 ( kCGEventFlagsChanged),与 Key Codes 查找的相同(当您打开该复选框时),每个事件的修饰符标志如上所示。(你是否真的可以通过产生这样的事件来触发听写,我不知道——你必须自己看看。)
  • 位布局并不是很重要,但如果你真的想知道,上半部分(“与设备无关”)标识打开了哪些修饰符,而下半部分(“与设备相关”,大概只存在于flags-changed 事件)标识刚刚按下哪些键来更改它们。
  • 修改键按下的次数可能是硬编码的(或者,如果不是,则在其他地方指定)。
于 2013-03-10T10:12:50.927 回答