【发布时间】:2016-11-23 21:41:30
【问题描述】:
我正在尝试创建一个 OS X 应用程序,它允许外部应用程序(即 textEdit)浮动在正在运行的应用程序之上而不保持焦点,但永远不会消失。基本上我想要做的是模仿 ForceQuit 应用程序(按 option-command-esc 来查看它),它总是在顶部,但并不总是有焦点。
我现在正在做的事情是这样的:
创建一个 NSTimer 以将其置于顶部:
_timer = [NSTimer scheduleTimerWithTimeInterval:0.1 target:self selector:@selector(keepTextEditOnTop) userInfo:nil repeats:YES];
...
将 textEdit 置于最前面:
- (void)keepTextEditOnTop {
AXUIElementRef appRef = AXUIElementCreateApplication(_textEditProcessID);
AXUIElementSetAttributeValue(appRef, kAXFrontmostAttribute, kCFBooleanTrue);
}
如果您单击它,textEdit 窗口将停留在顶部(使其失去焦点)。但是有两个问题。 1.) 它会短暂闪烁,让它回到顶部 2.) 它基本上始终保持焦点,因此您无法与底层应用程序交互。
从appRef中,可以得到窗口:
CFArrayRef windowList;
AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute, (CFTypeRef *)&windowList);
AXUIElementRef windowRef = (AXUIElementRef) CFArrayGetValueAtIndex(windowList, 0);
但我认为不可能将其转换为 NSWindow。如果我能做到这一点,我想我可以让它成为主窗口的子窗口,或者只是一个浮动窗口。
关于如何做到这一点的任何想法?
编辑 - 添加来自 @TheDarkKnight 的建议
我正在尝试这个:
- (void)testing{
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
for (NSMutableDictionary* entry in (__bridge NSArray*)windowList)
{
NSString* ownerName = [entry objectForKey:(__bridge id)kCGWindowOwnerName];
NSString *windowNum = [entry objectForKey:(__bridge id)kCGWindowNumber];
if([ownerName isEqualToString:@"Sublime Text"]){
[self holdToTheFront:[windowNum integerValue]];
}
}
CFRelease(windowList);
}
收到 EXC_BAD_ACCESS 错误,如下评论中所述:
- (void)holdToTheFront:(NSInteger)winNum {
objc_object* nsviewObject = reinterpret_cast<objc_object *>(winNum);
//Getting a "Thread 1:EXC_BAD_ACCESS (code=1, address=0x18)" at the line below:
NSWindow* nsWindowObject = ((id (*)(id, SEL))objc_msgSend)((__bridge NSView *)nsviewObject, sel_registerName("window"));
int NSWindowCollectionBehaviorCanJoinAllSpaces = 1 << 0;
((id (*)(id, SEL, NSUInteger))objc_msgSend)(nsWindowObject, sel_registerName("setCollectionBehavior:"), NSWindowCollectionBehaviorCanJoinAllSpaces);
}
【问题讨论】:
-
你有这方面的最新消息吗?
标签: c++ objective-c cocoa nswindow macos-carbon