OS X计算没有辅助功能访问的按下键 [英] OS X count pressed keys without accessibility access

查看:102
本文介绍了OS X计算没有辅助功能访问的按下键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现upwork.app可以计算没有辅助功能访问权限的按下键,但我不知道它是如何完成的.

I found that upwork.app can count pressed keys without accessibility access but I can not understand how it is done.

我读了很多这样的主题: OSX:检测系统范围的keyDown事件?

I read a lot of themes like this one: OSX: Detect system-wide keyDown events?

在所有主题中都说应该信任该过程为辅助设备启用访问权限",而我没有找到upwork.app如何在没有此功能的情况下跟踪键.

In all themes are saying that process should be trusted "Enable access for assistive devices" and I can not find how upwork.app can track keys without this.

这是跟踪事件的官方文档:
https://developer.apple.com/reference/appkit/nsevent/1535472-添加全局监控器以匹配事件

This is official documentation for tracking events:
https://developer.apple.com/reference/appkit/nsevent/1535472-addglobalmonitorforeventsmatchin

仅在启用辅助功能或信任您的应用程序具有辅助功能访问的情况下,才可以监视与键有关的事件.(请参阅AXIsProcessTrusted).

Key-related events may only be monitored if accessibility is enabled or if your application is trusted for accessibility access (see AXIsProcessTrusted).

在苹果邮件列表中说的是相同的:
http://lists.apple.com/archives/carbon- dev/2010/Feb/msg00043.html

In apple mail list is saying same:
http://lists.apple.com/archives/carbon-dev/2010/Feb/msg00043.html

我认为upwork.app使用了一些技巧.

I think that upwork.app use some hacks.

在无辅助功能访问的情况下,我该如何计算按下的键?

How I can count pressed keys without accessibility access?

推荐答案

在评论中仍未收到您的答复,但由于这可能还会对将来的其他人有所帮助,所以我还是决定回答.

Still haven't received your answer in the comments, but since that might also help other people in the future I decided to answer anyway.

使用IOKit,您可以检测键盘上是否有设备,并获取按键事件,例如设备事件.我已经使用它来检测操纵杆事件,但是它应该可以很好地与键盘配合使用.我认为所做的修改已经足够并且可以正常使用,但是我的Xcode现在正在更新,因此我还无法对其进行测试.

With the IOKit you can detect the keyboard has a device, and get the key press events like device events. I've used that to detect joystick events, but it should work with keyboards has well. I assume that the modifications that I made are enough and should work, however my Xcode is updating now, so I wasn't able to test it yet.

KeyboardWatcher.h文件:

#import <Foundation/Foundation.h>
#import <IOKit/hid/IOHIDManager.h>
#import <IOKit/hid/IOHIDKeys.h>

@interface KeyboardWatcher : NSObject{
   IOHIDManagerRef HIDManager;
}

@property (nonatomic) int keysPressedCount;

+(instancetype)sharedWatcher;
-(void)startWatching;
-(void)stopWatching;

@end

KeyboardWatcher.m文件:

#import "KeyboardWatcher.h"

@implementation KeyboardWatcher

static KeyboardWatcher *_sharedWatcher;

+(instancetype)sharedWatcher {
    @synchronized([self class]) {
        if (!_sharedWatcher){
            _sharedWatcher = [[KeyboardWatcher alloc] init];
        }
        return _sharedWatcher;
    }
    return nil;
}
-(instancetype)init {
    self = [super init];
    if (self){
        self.keysPressedCount = 0;
    }
    return self;
}

-(void)startWatching {
    [self watchDevicesOfType:kHIDUsage_GD_Keyboard];
}
-(void)watchDevicesOfType:(UInt32)deviceType {
    // Create an HID Manager
    HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);

    // Create a Matching Dictionary
    CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks,
                                                                                         &kCFTypeDictionaryValueCallBacks);

    // That will make the app just return the computer keyboards
    CFDictionarySetValue(matchDict, CFSTR(kIOHIDPrimaryUsageKey), CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &deviceType));

    // Register the Matching Dictionary to the HID Manager
    IOHIDManagerSetDeviceMatching(HIDManager, matchDict);

    // Register the HID Manager on our app’s run loop
    IOHIDManagerScheduleWithRunLoop(HIDManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);

    // Open the HID Manager
    IOReturn IOReturn = IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone);

    // Register input calls to Handle_DeviceEventCallback function
    IOHIDManagerRegisterInputValueCallback(HIDManager, Handle_DeviceEventCallback, nil);

    if (IOReturn) NSLog(@"IOHIDManagerOpen failed.");
}
-(void)stopWatching {
    HIDManager = NULL;
}

static void Handle_DeviceEventCallback (void *inContext, IOReturn inResult, void *inSender, IOHIDValueRef value){
    IOHIDElementRef element = IOHIDValueGetElement(value);          // Keyboard pressed key

    uint32_t uniqueIdentifier = IOHIDElementGetCookie(element);     // Unique ID of key
    int elementValue = (int)IOHIDValueGetIntegerValue(value);       // Actual state of key (1=pressed)

    NSLog(@"Unique ID = %u; Value = %d", uniqueIdentifier, elementValue);

    if (elementValue == 1) KeyboardWatcher.sharedWatcher.keysPressedCount++;
}

@end

如果要标识哪个唯一ID是哪个键,则可以使用以下枚举(代替导入Carbon,您可以创建一个CGKeyboardMapping.h文件并将其粘贴到其中): https://stackoverflow.com/a/16125341/4370893

In case you want to identify which unique ID is which key, you can use these enums (instead of importing Carbon you can just create a CGKeyboardMapping.h file and paste them there): https://stackoverflow.com/a/16125341/4370893

最后,为了使用它,您只需要这样做就可以开始监视键盘事件:

At last, in order to use it, you just need to do that to start watching for keyboard events:

[[KeyboardWatcher sharedWatcher] startWatching];

获得按键计数:

[[KeyboardWatcher sharedWatcher] keysPressedCount];

然后停止:

[[KeyboardWatcher sharedWatcher] stopWatching];

这些是我编写原始操纵杆代码的参考:

These were my references to write my original joystick code:

  • http://ontrak.net/xcode.htm
  • http://ontrak.net/xcode2.htm
  • https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/HID/new_api_10_5/tn2187.html
  • http://www.opensource.apple.com/source/IOHIDFamily/IOHIDFamily-315.7.16/IOHIDFamily/IOHIDUsageTables.h

更新完成后,我将测试代码并确定其是否有效.

As soon as the update finishes I will test the code and inform if it's working or not for sure.

编辑:刚刚测试过,并且可以正常工作.不要忘记将IOKit框架添加到项目中.

Just tested and it's working. Don't forget to add the IOKit framework to the project.

这篇关于OS X计算没有辅助功能访问的按下键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆