How to programatically get an OSX window id from a process id on 10.6? (using Applescript, Objective-C, whatever)

China☆狼群 提交于 2020-06-26 07:35:12

问题


I know that I can do

tell application "Safari" to id of window 1

to get the window ID of Safari. However, this only works for Applescriptable applications. I want to be able to write a program that will take a PID as input and output the window ID. (In case you are curious, this will be used in turn to supply the window ID to the undocumented "CGSMoveWorkspaceWindowList" to move applications between spaces on 10.6.)

According to this question, it is possible to do it via undocumented APIs in the OSX Accessibility API with Objective-C. Unfortunately, the author didn't specify any additional information about it.

Of course, I'm not married to Objective-C, I just want to get the WID from a PID by any means possible. One other possibility, if anyone knows how, is to get the WID from the currently activated/frontmost process (I have a command line tool to activate a given PID).

Edit: Thanks to weichsel pointing me down the right path, I made a program to output all window data.

#include <Carbon/Carbon.h>

// compile as such:
//  gcc -framework carbon -framework foundation GetWindowList.c

int main(int argc, char **argv) {

    CFArrayRef windowList;

    if (argc != 1) {
        printf("usage: %s\n", argv[0]);
        exit(1);
    }

    windowList = CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements, kCGNullWindowID);
    NSLog(CFSTR("Array: %@"), windowList);
    CFRelease(windowList);

}

Then, I used Python to parse all of the data, mostly because I have 0 idea on how to do that in Objective-C, and Python would probably be less lines of code anyway. =D

import os
import re

PID_WID_List = []
temp = os.popen('./GetWindowList 2>&1').read().strip().split('},')
for i in temp:
    match = re.search('kCGWindowOwnerPID = (\d+);', i)
    pid = match.group(1)
    match = re.search('kCGWindowNumber = (\d+);', i)
    wid = match.group(1)
    PID_WID_List.append((pid, wid))

Note that NSLog writes everything to system.log, so this method isn't suitable for an infinite checking loop.

Thanks again to weichsel.


回答1:


The question you linked to already contains a part of the answer.
The Objective-C way to get an ordered list of windows (including their ID and level) is the Quartz Window Services API (CGWindowList...).

Apple provides the "Son of Grab" sample code project, that allows you to explore all values returned by CGWindowListCopyWindowInfo:
https://developer.apple.com/library/mac/samplecode/SonOfGrab/

While the window information dictionary doesn't explicitly contain a "frontmost" key, you should be able to find the correct window by filtering the list for elements where kCGWindowLayer == 0 and choose the first element (the list is ordered front-to-back).
The dictionary also contains a kCGWindowOwnerPID key.



来源:https://stackoverflow.com/questions/16952055/how-to-programatically-get-an-osx-window-id-from-a-process-id-on-10-6-using-ap

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!