从 mac 上的活动窗口获取 PID、窗口 ID、进程名称和窗口名称的统一方法

问题描述 投票:0回答:1

我正在写一个应用程序,需要周期性的获取活动窗口的PID、进程名、窗口ID和窗口名。该程序是用 Go 编写的,但问题与进入 Mac 生态系统的任何 FFI 相关。我有两种方法,通过 AppleScript 和通过 Objective C。

两者都给出了75%的解决方案;缺少窗口 ID 或窗口名称。我想找到一个统一的解决方案来提供所有四个属性,而不是必须拼凑一个取决于我拥有的两种方法的解决方案。

AppleScript 方法;大多数情况下不提供 WindowNumber。

global activeApp, activePID, activeName, windowName
set windowName to ""
tell application "System Events"
    set activeApp to first application process whose frontmost is true
    set activePID to unix id of activeApp
    set activeName to name of activeApp
    tell process activeName
        try
            tell (1st window whose value of attribute "AXMain" is true)
                set windowName to value of attribute "AXTitle"
            end tell
        end try
    end tell
end tell
return ("{\"pid\":" & activePID & ",\"name\":\"" & activeName & "\",\"window\":\"" & windowName & "\"}" as text)

Objective C 方法;大多数情况下不提供 WindowName。

#include <Cocoa/Cocoa.h>
#include <CoreGraphics/CGWindow.h>

struct details {
   int wid;
   int pid;
   const char* name;
   const char* window;
};

int activeWindow(struct details *d)
{
    if (d == NULL) {
        return 0;
    }
    NSArray *windows = (NSArray *)CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements|kCGWindowListOptionOnScreenOnly,kCGNullWindowID);
    for(NSDictionary *window in windows){
        int WindowLayer = [[window objectForKey:(NSString *)kCGWindowLayer] intValue];
        if (WindowLayer == 0) {
            d->wid = [[window objectForKey:(NSString *)kCGWindowNumber] intValue];
            d->pid = [[window objectForKey:(NSString *)kCGWindowOwnerPID] intValue];
            d->name = [[window objectForKey:(NSString *)kCGWindowOwnerName] UTF8String];
            d->window = [[window objectForKey:(NSString *)kCGWindowName] UTF8String];
            return 1;
        }
    }
    return 0;
}
objective-c macos applescript
1个回答
0
投票
tell application "System Events"
    set frontProcess to 1st process whose frontmost is true
    set activePID to unix id of frontProcess
    set bundleID to bundle identifier of frontProcess
    set activeName to name of frontProcess
end tell

tell application id bundleID
    try
        set appName to name
        set windowID to id of front window
        set windowName to name of front window
    on error
        set windowID to my getFrontWindowID(appName)
        try
            tell application "System Events" to tell frontProcess to tell window 1 to set windowName to value of attribute "AXTitle"
        on error
            set windowName to ""
        end try
    end try
end tell

return {pid:activePID, processName:activeName, appName:appName, windowID:windowID, windowName:windowName}
--> {pid:9893, processName:"Avidemux2.7", appName:"Avidemux_2.7.8", windowID:5969, windowName:"Avidemux"}


on getFrontWindowID(appName)
    set JS to "ObjC.import('CoreGraphics');
Ref.prototype.$ = function() {
    return ObjC.deepUnwrap(ObjC.castRefToObject(this));
}
Application.prototype.getWindowList = function() {
    let pids = Application('com.apple.systemevents')
              .processes.whose({ 'bundleIdentifier':
                    this.id() }).unixId();

    return  $.CGWindowListCopyWindowInfo(
            $.kCGWindowListExcludeDesktopElements,
            $.kCGNullWindowID).$()
             .filter(x => pids.indexOf(x.kCGWindowOwnerPID) + 1
                       && x.kCGWindowLayer     == 0
                       && x.kCGWindowStoreType == 1
                       && x.kCGWindowAlpha     == 1
            ).map(x => [x.kCGWindowNumber]);           
}
Application('" & appName & "').getWindowList();"
    return (word 1 of (do shell script "osascript -l JavaScript -e " & quoted form of JS)) as integer
end getFrontWindowID
© www.soinside.com 2019 - 2024. All rights reserved.