前台将键盘事件立即注入NSRunningApplication中 [英] Inject keyboard event into NSRunningApplication immediately after foregrounding it

查看:139
本文介绍了前台将键盘事件立即注入NSRunningApplication中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将一个NSRunningApplication*实例放到前台,并注入一个键盘事件.

I am trying to bring to foreground a NSRunningApplication* instance, and inject a keyboard event.

NSRunningApplication* app = ...;
[app activateWithOptions: 0];
inject_keystrokes();

...无法注入键盘事件,但是:

... fails to inject keyboard events, but:

NSRunningApplication* app = ...;
[app activateWithOptions: 0];
dispatch_time_t _100ms = dispatch_time( DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC) );
dispatch_after(
               _100ms,
               dispatch_get_main_queue(),
               ^{ inject_keystrokes(); }
               );

...成功.

我想窗口在前景中渲染需要一定的时间,也许这发生在单独的线程上,这可以解释注入失败.

I imagine it takes a certain amount of time for the window to render in the foreground, and maybe this happens on a separate thread, and this explains the injection failure.

但是,这是一个非常丑陋的解决方案.它依赖于任意时间间隔.

However this is a very ugly solution. It relies on an arbitrary time interval.

以某种方式等待窗口完成前景将更加清洁.

It would be much cleaner to somehow wait for the window to complete foregrounding.

有什么办法吗?

PS inject_keystrokes()使用CGEventPost(kCGHIDEventTap, someCGEvent)

PPS参考:
-虚拟按键进入错误的应用程序
-将NSEvent发送到后台应用
- http://advinprog .blogspot.com/2008/06/so-you-want-to-post-keyboard-event-in.html

PPS Refs:
- Virtual keypress goes to wrong application
- Send NSEvent to background app
- http://advinprog.blogspot.com/2008/06/so-you-want-to-post-keyboard-event-in.html

推荐答案

NSRunningApplication上为KVO属性isActive添加观察者对我来说是可行的.

Adding an observer for the KVO property isActive on NSRunningApplication works for me.

for (NSRunningApplication* ra in [[NSWorkspace sharedWorkspace] runningApplications])
{
    if ([ra.bundleIdentifier isEqualToString:@"com.apple.TextEdit"])
    {
        [ra addObserver:self forKeyPath:@"isActive" options:0 context:ra];
        [ra retain];
        [ra activateWithOptions:0];
    }
}

// ...

- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
    if ([keyPath isEqualToString:@"isActive"])
    {
        NSRunningApplication* ra = (NSRunningApplication*) context;
        [ra removeObserver:self forKeyPath:@"isActive"];
        [ra release];
        inject_keystrokes();
    }
}

请注意,由于我没有将其保留在属性或ivar中,因此我手动保留并释放了NSRunningApplication以保持其引用有效.您必须小心,不要在仍附加观察者的情况下删除引用.

Note that I manually retain and then release the NSRunningApplication to keep its reference alive, since I'm not keeping it in a property or ivar. You have to be careful that the reference doesn't get dropped with the observer still attached.

这篇关于前台将键盘事件立即注入NSRunningApplication中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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