How would I programmatically activate i.e move-to-front-and-focus a window on macOS (not belonging to my app) given its Window ID
. My app would run with user grante
For anyone looking for an Objective C solution:
#import
#import
#import
#import
#import
bool activate_window_of_id(unsigned 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];
unsigned 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:@"\" 2>&1"] 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;
}
Note, unlike Daniel's answer, this will not just bring the specified application's windows to the front, it will also make sure the specific window whose id matches the one specified will be the topmost out of that app's collection of windows. It will return true on success, and false on failure. I noticed it brings to front for some apps but not for others. I'm not sure why. The code it is based on does not work as advertised for its original purpose. Although, it did help me a lot to get working all the stuff I needed to answer this question. The code my answer is based on can be found here. Ignore the original usage.