前台将键盘事件立即注入NSRunningApplication中 [英] Inject keyboard event into NSRunningApplication immediately after foregrounding it
问题描述
我正在尝试将一个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屋!