objective-c - 从有符号整数创建 CGEvent

标签 objective-c macos cocoa hotkeys bitmask

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

在尝试访问 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 中事件位掩码的人都可以看到,如果这些关键代码表示可以轻松地转换为事件,然后发射到蓝色中,那么它们将有多么有用。

最佳答案

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

2 × ⌘:
 1048576: 00000000000100000000000000000000
-1048577: 11111111111011111111111111111111

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

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

2 × Fn:
 8388608: 00000000100000000000000000000000
-8388609: 11111111011111111111111111111111

除此之外,我无法得知太多:

  • 假设正值是“真实的”值(请参阅我关于为什么有两个以及为什么所有四对都是互补的理论的评论), key 标识符至少高 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

因此, LCMDKEYMASK0b1000 ,而 RCMDKEYMASK0b10000 。这也与您找到的 left-⌘ 和 right-⌘ 值相匹配:左侧是 NX_COMMANDMASK | NX_DEVICELCMDKEYMASK ,而右侧是 NX_COMMANDMASK | NX_DEVICERCMDKEYMASK

据此,我可以得出结论:

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

关于objective-c - 从有符号整数创建 CGEvent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15319716/

相关文章:

iphone - 仅使用 objective-c 在 iPhone openGL ES 中绘制文本

objective-c - 离线生成二维码

python - 如何避免每次重新登录我的帐户,Selenium Python mac

macos - 是否可以将通过某个端口进入的 ssh 请求转发到另一台机器?

objective-c - 当动画可能发生时释放窗口

c++ - 在 Xcode 中将 C++ 与 OpenGL 结合使用

ios - 在 ios 中使用 googlemap 显示两个位置之间的路线?

objective-c - colorWithSRGBRed vs colorWithDeviceRed vs colorWithCalibratedRed 有什么区别

multithreading - Core Data,在后台线程中修改 NSManagedObject

objective-c - 添加多个 NSSlider 以编程方式查看