Macos 在前景化后立即将键盘事件注入NSRunningApplication
我正在尝试将Macos 在前景化后立即将键盘事件注入NSRunningApplication,macos,nswindow,nsevent,nsrunningapplication,foregroundnotification,Macos,Nswindow,Nsevent,Nsrunningapplication,Foregroundnotification,我正在尝试将NSRunningApplication*实例带到前台,并插入一个键盘事件 NSRunningApplication* app = ...; [app activateWithOptions: 0]; inject_keystrokes(); 。。。无法注入键盘事件,但: NSRunningApplication* app = ...; [app activateWithOptions: 0]; dispatch_time_t _100ms = dispatch_time( DIS
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(); }
);
。。。成功
我想窗口在前景中渲染需要一定的时间,这可能发生在一个单独的线程上,这就解释了注入失败的原因
然而,这是一个非常丑陋的解决方案。它依赖于任意的时间间隔
以某种方式等待窗口完成前景化会更干净
有没有办法做到这一点
PSinject_keystrokes()
使用CGEventPost(kCGHIDEventTap,someCGEvent)
PPS参考文献:-
-
-在
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
上为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中。你必须小心,不要在观察者仍然连接的情况下删除引用。你是否尝试使用CGEventPostToPid
将事件发布到应用程序?我刚刚尝试,不幸的是它不起作用。你是否尝试使用CGEventPostToPid
将事件发布到应用程序?我刚刚尝试,不幸的是它不起作用。