从有符号整数创建CGEvent

Cod*_*aFi 2 macos cocoa hotkeys objective-c bitmask

在我继续之前,我想在这篇文章的序言中说这可能是最讨厌,彻头彻尾的邪恶,令人讨厌的话题,所以我不希望任何答案都包含"合法"代码.

在尝试访问OS X Mountain Lion用于包含热键组合以激活听写的内部首选项文件时,我遇到了一些精美的有符号整数,其中包含System Preferences.app中定义的键代码.问题是,我能想到把它们变成a的唯一方法CGEvent是通过并基本解析出给定密钥代码的位掩码,这是一种潜在的无结果和烦人的努力.而且因为CGEvent方便地为内部struct(__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];
}
Run Code Online (Sandbox Code Playgroud)

任何熟悉HIToolbox中事件位掩码的人都可以看到这些关键代码表示有多么有用,只要它们可以很容易地变成事件然后被激发为蓝色.

Pet*_*sey 6

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

2 × ?:
 1048576: 00000000000100000000000000000000
-1048577: 11111111111011111111111111111111

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

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

2 × Fn:
 8388608: 00000000100000000000000000000000
-8388609: 11111111011111111111111111111111
Run Code Online (Sandbox Code Playgroud)

除此之外,我无法理解这一点:

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

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

在我的MacBook Air上,运行密钥代码为我提供了以下输出:

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
Run Code Online (Sandbox Code Playgroud)

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

  • 每次按⌘键,修改器状态都会更改为1048000范围内的某些内容.
  • 当我按Fn时,修饰符状态更改为8388864.Yerrs为8388608.

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

NSCommandKeyMask            = 1 << 20,
NSFunctionKeyMask           = 1 << 23,
Run Code Online (Sandbox Code Playgroud)

噢!嗨.

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

NSDeviceIndependentModifierFlagsMask    = 0xffff0000UL
Run Code Online (Sandbox Code Playgroud)

这意味着该低 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
Run Code Online (Sandbox Code Playgroud)

LCMDKEYMASK是的,是0b1000,RCMDKEYMASK是的0b10000.这也与您找到的左⌘和右⌘值匹配:左边是NX_COMMANDMASK | NX_DEVICELCMDKEYMASK,右边是NX_COMMANDMASK | NX_DEVICERCMDKEYMASK.

由此,我可以得出结论:

  • 这些数字不是完整的CGEvents.
  • 在每对中,正值是修饰符标志掩码,负值只是其补码.
  • 您需要生成的事件是修饰符更改事件(kCGEventFlagsChanged),与键代码查找相同(当您打开该复选框时),每个事件的修饰符标志如上所示.(你是否真的可以通过产生这样的事件来触发听写,我不知道 - 你必须亲自看看.)
  • 位布局不是非常重要,但是如果你真的想知道,上半部分("设备无关")识别哪些修饰符被打开,下半部分("设备相关"并且可能仅存在于flags-changed事件)标识刚刚按下哪些键来更改它们.
  • 据推测,修改键按下的次数是硬编码的(或者,如果没有,则在其他地方指定).

  • 我的,我的,答案是什么.为什么,我认为这值得赏心悦目.男人,坚持72个小时. (2认同)