Objective c MacOS-根据窗口ID激活窗口

Objective c MacOS-根据窗口ID激活窗口,objective-c,swift,macos,cocoa,core-graphics,Objective C,Swift,Macos,Cocoa,Core Graphics,是否可以基于从返回的值创建一个窗口?(即使用。) 编辑: 我应该指定我的应用程序(将以可访问性权限运行)需要能够在其他应用程序的windows上执行此操作 自从发布这个问题以来,我发现了axuielementperformation。我的方向对吗 还是在我的代码中运行AppleScript桥是最好的方法 您可以通过pid附加到进程并获取其窗口。然后使用kAXRaiseAction将它们带到前面,如下所示: AXUIElementRef element = AXUIElementCreateApp

是否可以基于从返回的值创建一个窗口?(即使用。)

编辑:

我应该指定我的应用程序(将以可访问性权限运行)需要能够在其他应用程序的windows上执行此操作

自从发布这个问题以来,我发现了
axuielementperformation
。我的方向对吗


还是在我的代码中运行AppleScript桥是最好的方法

您可以通过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);
AXUIElementRef元素=AXUIElementCreateApplication(pid);
if(元素){
CFArrayRef阵列;
AxUIElementCopyAttributeValue(元素、kAXWindowsAttribute、0、99999和数组);
if(数组==nullptr)
返回;
NSArray*windows=(NSArray*)CfBrigingRelease(数组);
对于(整数i=0;i

无需释放
array
windows
。数组中的子数组将自动处理,数组将桥接到ARC发布的NSArray上。

与Mike Lischke已经分享的答案相比,我的答案有点过于复杂,但我已经将其发布到了另一个SO问题上,我认为它更接近您的需要:

#import <Cocoa/Cocoa.h>
#import <libproc.h>
#import <string.h>
#import <stdlib.h>
#import <stdio.h>

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;
}
#导入
#进口
#进口
#进口
#进口
bool激活\u id的\u窗口(未签名的长wid){
布尔成功=假;
const CGWindowLevel kScreensaverWindowLevel=CGWindowLevelForKey(kCGScreenSaverWindowLevelKey);
CFArrayRef windowArray=CGWindowListCopyWindowInfo(KCGWindowListOptionnsScreenOnly | KCGWindowListExcludedSktopElements,kCGNullWindowID);
CFIndex windowCount=0;
如果((windowCount=CFArrayGetCount(windowArray))){
对于(CFIndex i=0;i&1”]UTF8String],“r”);
while(getline(&指针,&缓冲区大小,文件)!=-1)
[array addObject:[NSString stringWithUTF8String:指针]];
char*error=(char*)[[array componentsJoinedByString:@”“]UTF8String];
如果(strlen(error)>0&&error[strlen(error)-1]=='\n')
错误[strlen(error)-1]='\0';
如果([[NSString stringWithUTF8String:error]IsequalString:@”“]))
成功=真实;
[阵列释放];
自由(指针);
pclose(文件);
打破
}
}
}
}
}
}
CFRelease(windowArray);
回归成功;
}

它所基于的代码不符合其原始用途的宣传。尽管如此,它确实帮了我很大的忙,帮了我解决这个问题所需要的所有东西

您自己的应用程序或任何正在运行的应用程序?的其他应用程序。请参阅编辑。我想专门使用窗口ID来标识窗口。自从发布这个问题以来,我发现没有直接的方法可以做到这一点。但可以做的是根据窗口的标题、位置和大小匹配窗口(由CGWindowListCopyWindowInfo()返回的窗口与由AxUIElementCopyAttributeValue()返回的窗口)。在(罕见的)无法找到唯一匹配的情况下,可以使用AX api将窗口大小更改1像素左右,从而找到与感兴趣的CGWindow匹配的窗口。但是,是的,AXRaise是随后要做的事情。然后是NSRunningApplication.activate(),我喜欢这个答案的简单性+1.