Mavericks +中的CGEventTapCreateForPSN(不建议使用GetCurrentProcess) [英] CGEventTapCreateForPSN in Mavericks+ (GetCurrentProcess deprecated)

查看:126
本文介绍了Mavericks +中的CGEventTapCreateForPSN(不建议使用GetCurrentProcess)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用CGEventTapCreateForPSN来捕获和过滤应用程序的密钥.我对拦截其他应用程序的事件不感兴趣.我很确定事件轻敲对于我的目的来说太过分了,但是我一直找不到更好的方法,并且使用事件轻敲还是可以的.

I am using CGEventTapCreateForPSN to trap and filter keys for my application. I'm not interested in intercepting events for other applications. I'm pretty sure an event tap is too heavy handed for my purpose, but I've been unable to find a better way, and using the event tap works.

具体来说,这段代码可以满足我的要求.

Specifically, this code does what I want.

GetCurrentProcess(&psn);
CFMachPortRef eventTap = CGEventTapCreateForPSN(
    &psn,
    kCGHeadInsertEventTap,
    kCGEventTapOptionDefault,
    CGEventMaskBit(kCGEventKeyDown)
        | CGEventMaskBit(kCGEventKeyUp),
    eventCallback,
    userInfo);

我的回调处理得很好,仅从当前应用程序中拦截了事件.

And my callback is handled nicely, with the events being intercepted from the current application only.

不幸的是,从10.9开始,所有获取当前ProcessSerialNumber的方法都已被弃用.通过这种初始化,有一种古老的标准方法可以使ProcessSerialNumber传递给同一过程中的其他例程.

Unfortunately, all the methods to get the current ProcessSerialNumber have been deprecated as of 10.9. There is an old standard way of getting the ProcessSerialNumber to pass to other routines in the same process, with this initialization...

ProcessSerialNumber psn = { 0, kCurrentProcess };

,但是在调用CGEventTapCreateForPSN时不起作用.头文件docs指出了很多,以下代码段返回NULL作为确认.

but that does not work when calling CGEventTapCreateForPSN. The header file docs indicates as much, and the following code snippet returns NULL as confirmation.

ProcessSerialNumber psn = { 0, kCurrentProcess };
CFMachPortRef eventTap = CGEventTapCreateForPSN(
    &psn,
    kCGHeadInsertEventTap,
    kCGEventTapOptionDefault,
    CGEventMaskBit(kCGEventKeyDown)
        | CGEventMaskBit(kCGEventKeyUp),
    eventCallback,
    userInfo);

我可以使用CGEventTapCreate,但是它会窃听整个主机,然后我需要过滤不定向到我的应用程序的所有内容,并且CGEventTapProxy是不透明的,并且我不知道如何使用它来确定是否是我的应用程序.

I can use CGEventTapCreate but it taps the entire host, and I would then need to filter anything not directed to my application, and the CGEventTapProxy is opaque, and I don't know how to use it to determine if its my app or not.

我已验证不赞成使用的代码仍然可以使用,但是Apple可以决定随时将其删除.那么,有没有人知道我应该如何在Mavericks及以后的地区呼叫CGEventTapCreateForPSN?

I have verified that the deprecated code still works, but Apple can decide to remove it at any time. So, does anyone have an idea how I should proceed for calling CGEventTapCreateForPSN in Mavericks and beyond?

谢谢!

更新

在10.11(我认为是El Capitan)中,添加了一个新功能.尽管文档数量为零,但它的签名几乎与CGEventTapCreateForPSN完全相同.

In 10.11 (I think that was El Capitan), a new function was added. While it has zero documentation, it has almost the exact same signature as CGEventTapCreateForPSN.

CFMachPortRef CGEventTapCreateForPSN(
    void *processSerialNumber,
    CGEventTapPlacement place,
    CGEventTapOptions options,
    CGEventMask eventsOfInterest,
    CGEventTapCallBack callback,
    void *userInfo);

CFMachPortRef CGEventTapCreateForPid(
    pid_t pid,
    CGEventTapPlacement place,
    CGEventTapOptions options,
    CGEventMask eventsOfInterest,
    CGEventTapCallBack callback,
    void *userInfo);

因此,不需要使用过的功能,因为PID可以用作第一个参数.

Thus, the deprecated function is not needed since the PID can be used as the first parameter.

推荐答案

为此,您应该将NSApplication子类化并重写- (void)sendEvent:(NSEvent *)theEvent方法. 来自文档:

I think you should subclass NSApplication and override - (void)sendEvent:(NSEvent *)theEvent method for this purpose. From docs:

您很少应该真正需要创建自定义NSApplication子类.与某些面向对象的库不同,Cocoa不需要您子类化NSApplication即可自定义应用程序行为.相反,它为您提供了许多其他自定义应用程序的方式.

You rarely should find a real need to create a custom NSApplication subclass. Unlike some object-oriented libraries, Cocoa does not require you to subclass NSApplication to customize app behavior. Instead it gives you many other ways to customize an app.

也:

重要

许多AppKit类都依赖于NSApplication类,并且在此类完全初始化之前可能无法正常工作.因此,例如,您不应尝试从NSApplication子类的初始化方法中调用其他AppKit类的方法.

Many AppKit classes rely on the NSApplication class and may not work properly until this class is fully initialized. As a result, you should not, for example, attempt to invoke methods of other AppKit classes from an initialization method of an NSApplication subclass.

因此,您可以拦截通过应用程序传递的所有事件,并调用自定义的NSApplicationDelegate继承的协议方法.

Thus, you can intercept all the events passed though your application and call custom NSApplicationDelegate-inherited protocol methods.

// in SubApplication.h

@protocol ExtendedApplicationDelegate : NSApplicationDelegate

- (void)applicationDidTrapSomeInterestingEvent:(NSEvent *)event;

@end

// in SubApplication.m

- (void)sendEvent:(NSEvent *)event
{
    if ([event type] == NSKeyDown && [event keyCode]==_someCode)
    {
      // call application delegate method
    }
    [super sendEvent:event];
}

我不确定这种方法是否可以解决问题,但您仍然可以尝试.

I'm not sure if this approach solves the problem but you still make a try.

这篇关于Mavericks +中的CGEventTapCreateForPSN(不建议使用GetCurrentProcess)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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