根据activate (bring to the fore)返回的值,是否可以CGWindowListCopyWindowInfo
一个窗口? (即使用window ID (kCGWindowNumber
) or something else。)
编辑:
我应该指定我的应用程序(使用辅助功能权限运行)需要能够为其他应用程序的窗口执行此操作。
自发布问题后我发现AXUIElementPerformAction
。我是否正朝着正确的方向前进?
或者在我的代码中运行AppleScript网桥是最好的方法吗?
答案 0 :(得分:0)
您可以通过pid附加到进程并获取其窗口。然后使用kAXRaiseAction
将它们放在前面,如下所示:
AXUIElementRef element = AXUIElementCreateApplication(pid);
if (element) {
CFArrayRef array;
AXUIElementCopyAttributeValues(element, kAXWindowsAttribute, 0, 99999, &array);
if (array == nullptr)
return;
NSArray *windows = (NSArray *)CFBridgingRelease(array);
for (NSUInteger i = 0; i < windows.count; ++i) {
AXUIElementRef ref = (__bridge AXUIElementRef)(windows[i]);
AXError error = AXUIElementPerformAction(element, kAXRaiseAction);
// handle error
}
}
CFRelease(element);
无需释放阵列或窗口。数组中的子节点会自动处理,并且数组将桥接到ARC发布的NSArray。
答案 1 :(得分:0)
与Mike Lischke已经分享的答案相比,我的答案有些复杂,但是我已经将其发布在另一个SO问题上,我认为它与您的需求有点接近:
#import <Cocoa/Cocoa.h>
#import <libproc.h>
#import <string.h>
#import <stdlib.h>
#import <stdio.h>
bool activate_window_of_id(long wid) {
bool success = false;
const CGWindowLevel kScreensaverWindowLevel = CGWindowLevelForKey(kCGScreenSaverWindowLevelKey);
CFArrayRef windowArray = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
CFIndex windowCount = 0;
if ((windowCount = CFArrayGetCount(windowArray))) {
for (CFIndex i = 0; i < windowCount; i++) {
NSDictionary *windowInfoDictionary = (__bridge NSDictionary *)((CFDictionaryRef)CFArrayGetValueAtIndex(windowArray, i));
NSNumber *ownerPID = (NSNumber *)(windowInfoDictionary[(id)kCGWindowOwnerPID]);
NSNumber *level = (NSNumber *)(windowInfoDictionary[(id)kCGWindowLayer]);
if (level.integerValue < kScreensaverWindowLevel) {
NSNumber *windowID = windowInfoDictionary[(id)kCGWindowNumber];
if (wid == windowID.integerValue) {
CFIndex appCount = [[[NSWorkspace sharedWorkspace] runningApplications] count];
for (CFIndex j = 0; j < appCount; j++) {
if (ownerPID.integerValue == [[[[NSWorkspace sharedWorkspace] runningApplications] objectAtIndex:j] processIdentifier]) {
NSRunningApplication *appWithPID = [[[NSWorkspace sharedWorkspace] runningApplications] objectAtIndex:j];
[appWithPID activateWithOptions:NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps];
char buf[PROC_PIDPATHINFO_MAXSIZE];
proc_pidpath(ownerPID.integerValue, buf, sizeof(buf));
NSString *buffer = [NSString stringWithUTF8String:buf];
long location = [buffer rangeOfString:@".app/Contents/MacOS/" options:NSBackwardsSearch].location;
NSString *path = (location != NSNotFound) ? [buffer substringWithRange:NSMakeRange(0, location)] : buffer;
NSString *app = [@" of application \\\"" stringByAppendingString:[path lastPathComponent]];
NSString *index = [@"set index of window id " stringByAppendingString:[windowID stringValue]];
NSString *execScript = [[index stringByAppendingString:app] stringByAppendingString:@"\\\" to 1"];
char *pointer = NULL;
size_t buffer_size = 0;
NSMutableArray *array = [[NSMutableArray alloc] init];
FILE *file = popen([[[@"osascript -e \"" stringByAppendingString:execScript] stringByAppendingString:@"\""] UTF8String], "r");
while (getline(&pointer, &buffer_size, file) != -1)
[array addObject:[NSString stringWithUTF8String:pointer]];
char *error = (char *)[[array componentsJoinedByString:@""] UTF8String];
if (strlen(error) > 0 && error[strlen(error) - 1] == '\n')
error[strlen(error) - 1] = '\0';
if ([[NSString stringWithUTF8String:error] isEqualToString:@""])
success = true;
[array release];
free(pointer);
pclose(file);
break;
}
}
}
}
}
}
CFRelease(windowArray);
return success;
}
该代码所基于的代码无法按其原始目的进行宣传。虽然,这确实对我帮助我解答该问题所需的全部工作有很大帮助。 The code my answer is based on can be found here.随时用Mike的代码替换管道评估的AppleScript。