Objective c OSX:如何检测任务控制是否正在运行?
当任务控制运行时,它会阻止应用程序接收键盘和鼠标事件。它还让最后一个运行的应用程序认为它仍然有焦点。这对我来说是个问题,因为如果我在启动任务控制时按住鼠标按钮或键,我不会收到keyUp或mouseUp事件,并且我的应用程序会像按住鼠标按钮或键一样运行 我想要一种方法,可以在任务控制处于活动状态时读取键盘和鼠标事件,也可以检测任务控制处于活动状态。理想情况下,我希望能够做到后者,因为在任务控制运行时,我无法有效地使用我的应用程序 我尝试了几件运气不佳的事情:Objective c OSX:如何检测任务控制是否正在运行?,objective-c,macos,cocoa,Objective C,Macos,Cocoa,当任务控制运行时,它会阻止应用程序接收键盘和鼠标事件。它还让最后一个运行的应用程序认为它仍然有焦点。这对我来说是个问题,因为如果我在启动任务控制时按住鼠标按钮或键,我不会收到keyUp或mouseUp事件,并且我的应用程序会像按住鼠标按钮或键一样运行 我想要一种方法,可以在任务控制处于活动状态时读取键盘和鼠标事件,也可以检测任务控制处于活动状态。理想情况下,我希望能够做到后者,因为在任务控制运行时,我无法有效地使用我的应用程序 我尝试了几件运气不佳的事情: 使用AddGlobalMonitor或
[[NSRunningApplication currentApplication]{isActive,ownsMenuBar}]
。
显然,我的应用程序是活动的,即使它没有接收事件李>
[NSApp keyWindow]!=无
。
显然,我的一个窗口应该接收关键事件。他们都不是[NSWorkspace runningApplications]
返回的正在运行的应用程序之一。任务控制在运行时不显示在此列表中[NSEvent pressedMouseButtons]
查询按下按钮的状态。我只是从NSLeftMouseDown和NSLeftMouseUp事件中跟踪我认为鼠标状态应该是什么,并经常将其与[NSEvent pressedMouseButtons]
进行比较,以确保它们一致。如果不是,那么我知道有什么东西劫持了我的NSLeftMouseUp事件,并相应地采取行动
对于键盘,我找不到查询键盘状态的方法,因此无法进行类似的解决方法。我最后禁用了使用when键切换应用程序。可能是我遗漏了什么,但您是否尝试使用事件点击而不是全局监视?您是否使用NSTask在bash级别进行了尝试?类似于
ps-faxU
的东西应该列出所有正在运行的进程,然后您可以解析输出,或者实际上您可以使用ps-faxU | grep-i“任务控制”
(在我的脑海中,我不确定如何调用该进程,但类似“任务控制”的东西似乎是合法的)。也许不是最优雅的解决方案,但如果没有其他解决方案,它可能是值得的。看来DTrace确实能够看到任务控制被激活。尝试运行:
sudo fs|u用法-filesys|grep任务
从命令行,然后从/Application文件夹启动任务控制应用程序
您应该看到很多与任务控制启动相关的输出。不幸的是,使用键盘快捷键或滑动并没有显示相同的输出。当然,在生产代码中使用DTrace并不是我真正推荐的做法。至少在OS X 10.10中,您可以使用此代码检查任务控制是否处于活动状态:
func missionControlIsActive() -> Bool
{
var result: Bool = false
let windowInfosRef = CGWindowListCopyWindowInfo(CGWindowListOption(kCGWindowListOptionOnScreenOnly), CGWindowID(0)) // CGWindowID(0) is equal to kCGNullWindowID
let windowList: NSArray = windowInfosRef.takeRetainedValue() // We own the returned CFArrayRef
for entry in windowList
{
if (entry.objectForKey("kCGWindowOwnerName") as! String) == "Dock"
{
var bounds: NSDictionary = entry.objectForKey("kCGWindowBounds") as! NSDictionary
if (bounds.objectForKey("Y") as! NSNumber) == -1
{
result = true
}
}
}
return result
}
简而言之,该代码检查OSX Dock进程拥有的特定窗口是否在屏幕上可见,以及它是否位于特定位置。如果两个条件都满足,任务控制将立即激活。代码将在沙盒应用程序中工作,不需要辅助设备的权限。C++和Qt实现在最新的OS X中工作
bool Window::missionControlIsActive() {
bool result = false;
CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly+kCGWindowListExcludeDesktopElements, kCGNullWindowID);
for (int i = 0; i < CFArrayGetCount(windows) ; i++) {
auto cfMutableDictionaryRef_dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex( windows, i );
auto cfStringRef_name = (CFStringRef)CFDictionaryGetValue(cfMutableDictionaryRef_dict, kCGWindowName);
if (QString::fromCFString(cfStringRef_name) != u"") continue;
auto cfStringRef_ownerName = (CFStringRef)CFDictionaryGetValue(cfMutableDictionaryRef_dict, kCGWindowOwnerName);
if (QString::fromCFString(cfStringRef_ownerName) != u"Dock") continue;
auto cfDictRef_bounds = (CFDictionaryRef)CFDictionaryGetValue(cfMutableDictionaryRef_dict, kCGWindowBounds);
auto cfNumRef_bounds_Y = (CFNumberRef)CFDictionaryGetValue(cfDictRef_bounds, QString("Y").toCFString());
double num;
CFNumberGetValue(cfNumRef_bounds_Y, kCFNumberFloat64Type, &num);
if (num > 1.0 and num < 1000000) continue;
result = true;
break;
}
CFRelease(windows);
return result;
}
bool Window::missionControlIsActive(){
布尔结果=假;
CFArrayRef windows=CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly+kCGWindowListExcludeDesktopElements,kCGNullWindowID);
对于(int i=0;i1.0且num<1000000)继续;
结果=真;
打破
}
CFRelease(windows);
返回结果;
}
来自文档:“只有在启用了可访问性或您的应用程序受信任可访问性访问(请参阅AXIsProcessTrusted)的情况下,才能监视与密钥相关的事件。”–这可能就是您没有获得密钥事件的原因。在系统的可访问性首选项中启用“辅助设备访问”,并查看是否有任何变化。没错,启用可访问性确实会给我全局关键事件,但在任务控制处于活动状态时不会。我建议您提交错误报告:developer.apple.com/bugreporter-另外,最好让支持者想出解决方案,而不是提出具体的要求。也就是说,缺陷报告应该只清楚、简洁地识别问题。谢谢,我已经向苹果提交了一份缺陷报告。如果我从他们那里得到一个解决方案,我会向他们汇报。另请看这个非常相关的问题:我在终端上试过了。不幸的是,任务控制是存在的