将键盘事件置于前台后立即将其注入 NSRunningApplication
Inject keyboard event into NSRunningApplication immediately after foregrounding it
我正在尝试将一个 NSRunningApplication*
实例置于前台,并注入一个键盘事件。
NSRunningApplication* app = ...;
[app activateWithOptions: 0];
inject_keystrokes();
...无法注入键盘事件,但是:
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(); }
);
...成功。
我想 window 在前台渲染需要一定的时间,也许这发生在一个单独的线程上,这解释了注入失败。
然而,这是一个非常丑陋的解决方案。它依赖于任意时间间隔。
以某种方式等待 window 完成前景化会更干净。
有什么办法吗?
PS inject_keystrokes()
使用 CGEventPost(kCGHIDEventTap, someCGEvent)
PPS 参考:
-
- Send NSEvent to background app
- http://advinprog.blogspot.com/2008/06/so-you-want-to-post-keyboard-event-in.html
在 NSRunningApplication
上为 KVO 属性 isActive
添加一个观察者对我有用。
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();
}
}
请注意,我手动保留然后释放 NSRunningApplication
以使其引用保持活动状态,因为我没有将其保存在 属性 或 ivar 中。您必须小心,不要在观察者仍然附加的情况下删除引用。
我正在尝试将一个 NSRunningApplication*
实例置于前台,并注入一个键盘事件。
NSRunningApplication* app = ...;
[app activateWithOptions: 0];
inject_keystrokes();
...无法注入键盘事件,但是:
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(); }
);
...成功。
我想 window 在前台渲染需要一定的时间,也许这发生在一个单独的线程上,这解释了注入失败。
然而,这是一个非常丑陋的解决方案。它依赖于任意时间间隔。
以某种方式等待 window 完成前景化会更干净。
有什么办法吗?
PS inject_keystrokes()
使用 CGEventPost(kCGHIDEventTap, someCGEvent)
PPS 参考:
-
- Send NSEvent to background app
- http://advinprog.blogspot.com/2008/06/so-you-want-to-post-keyboard-event-in.html
在 NSRunningApplication
上为 KVO 属性 isActive
添加一个观察者对我有用。
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();
}
}
请注意,我手动保留然后释放 NSRunningApplication
以使其引用保持活动状态,因为我没有将其保存在 属性 或 ivar 中。您必须小心,不要在观察者仍然附加的情况下删除引用。